Pythonのシステムコール回数はC言語の20倍だった

 Linuxを学ぶに当たって、自分で適当に遊びつつ、Linuxの入門書を買って色々読んでいるのだが、武内覚さんというカーネルハッカーの方が書いた「Linuxのしくみ」というストレートなタイトルの本が面白い。まだ序盤だが、結構面白かったのが今回の記事の題名の話だ。Hello WorldC言語Pythonで実行してみると、後者のシステムコールはなんと20倍だったのだ。当たり前だがPythonがクソとか言いたいわけでは全くない。単純に面白いと思ったので、これについて書く。

システムコールとは

 プログラムを実行するときには、CPUを介してメモリやI/Oや画面などにアクセスする。これらは全てハードウェアである。各々のプログラムはいくつかのプロセスとして動作するが、これらのプロセスから直接ハードウェアにアクセスすることはできない。OSに対して、「ハードウェアへアクセスしてくれ!」と頼むことでそれを実現している。この依頼がシステムコールである。
すべてのプログラムが個別にハードウェアへアクセスするという仕組みだと、それの処理をすべてのプログラム毎で書かなくてはならないし、そうでなくとも言語毎にモジュールを用意しなければならない。ハードウェアの種類は膨大なので、それぞれのドライバに合わせたものを作らなくてはならない。
 それに現代ではセキュリティの問題もある。たとえばブラウザが、javascriptが直接ハードウェアにアクセス出来たら、別の用途で開いているExcelシートや、場合によってはデータベースの中身を盗み見たり、好き勝手に書き換えたりできてしまう。これでは大問題だ。
ちなみに一時期IntelのCPUで問題になったのはこの部分で、CPUの投機実行という処理をうまく使うことで、あるプロセスから別プロセスへアクセス出来てしまうというセキュリティ上の問題だった。これはOSの問題ではなくCPU側の問題である。

システムコールを捕捉する

C言語PythonでそれぞれHello Worldを表示するプログラムを書く(この本はC言語の勉強にもなるので助かる)。

hello.c

#include <stdio.h>

int main(void){
    puts("hello world");
    return 0;
}

C言語コンパイルは、cc -o hello hello.c

hello.py

print("hello world")

Pythonは3系統を前提に書いている

システムコールを比較する

 ってなわけで用意ができたら、以下のコマンドを実行する。

C言語: strace -o helloC.log ./hello
Python: strace -o helloPy.log python3 ./hello.py

Pythonの実行コマンドは環境によって違うだろう。Ubuntuだとpython3だったはず。僕はCentOS7にyumでPython3.6を入れて実行しているので上記のようになった。
straceはSystem Traceの略だろうか。要はシステムコールの内容を出力してくれるコマンドだ。oオプションをつけると、ファイルに出力することができる。あとはcatなんかでログを見てみる。
 重要なのはログの下から10行目以内くらいにある、write(1, "hello world\n"), 12)だ。これで画面に「hello world」を出力している。それを実行するまでに、僕の環境だとC言語では約25行、Pythonだと500行程度のシステムコールを実施していた。C言語が速いというのは本当だったということがわかる。

参考書籍