Computer Systems: A Programmer’s Perspective という本を読んだので読書メモ。
プログラムがCPUやメモリをどのように扱うかという、低レイヤーの概観を与えてくれる本。 タイトルに“A Programmer’s Perspective“とあるように、職業プログラマー向けの本であって、低レイヤーのハードウェア・ソフトウェアを作る専門家向けの本ではない。 プログラムを実行する時に under the hood で何が起きているかという mental model を獲得することで、より速いコードやよりメモリ効率の良いコードを書けるようになるのが目的とのこと。
僕は大学・大学院でずっと物理学ばかりやっていて、コンピュータ・サイエンスをまともに学んでいないのが悩みだったが、この本を読んである程度雰囲気は掴めるようになったと思う。 読んだきっかけは、Teach Yourself Computer Science というサイト。他にもCSの勉強に良さそうな資料が色々挙げられている。
プログラミング経験は当然必要。また解説用のコードは基本的にCなので、Cの読み書きができる必要がある。ポインタとか malloc
とかは知っていないと読むのは辛いと思う。ポインタがオブジェクトが格納されているメモリのアドレスだってことは知ってるけど、それって具体的にCPUやメモリはどう扱っているの?というレベルの人1 が読むとちょうど良い気がする。
整数や浮動小数点数の二進法表現を詳細に解説し、x86-64の命令セットについて学ぶ。Cのコードをアセンブリ言語に変換して、元のコードと対応づけて読めるようになるということを目指している。また、x86-64に似せた独自のY86-64というプロセッサーの設計を通して、CPUのパイプライン処理についても勉強する。
僕は今まで、コードをテキストファイルに書いてコンパイルすると謎の仕組みで謎のバイナリが吐き出されるという認識しか持っていなかったが、アセンブリがなんとなく読めるようになることでCのコードがどう変換されてマシン語になるのか雰囲気がわかるようになった。
また、これまでに学んだ知識をベースにしたプログラムの最適化も行う。オーダーの改善ではなく、CPUを最大限効率よく使うことによる $\mathcal O(1)$ の改善をしているのが面白かった。「カリカリにチューンする」というのはこういうことか。
リンク・例外・仮想メモリについて学ぶ。例外の章で初めてプロセスという概念が出てくる。
例外の章ではコントロールフローの制御の仕方を学び、ちょっとしたシェルを作成する。普段多用しているシェルという道具の仕組みがわかって楽しかった。
仮想メモリはこの本の集大成の一つで、ハードウェアとOSが協調してメモリを管理していることを学ぶ。
また malloc
等も掘り下げて説明されている。自分は今まで malloc
したら要求したメモリ分だけヒープが消費されるみたいな雑な感覚しか持っていなかったが、実際には fragmentation を抑えて効率的にメモリを扱えるようにOSが大変な努力をしていることがわかった。実際に簡単なメモリアロケーション・プログラムを作成してちゃんと動くことが確認できるのも面白かった。
Part III ではより進んで、I/O・ネットワーク・concurrency について学ぶ。 Cで小さいWEBサーバーを作成し、それを multi-process, multiplex, multi-thread それぞれで並行に実行する方法を学ぶ。
特にネットワークに関しては今までどうやって動いているのか全くイメージが持てていなかったので、ソケットというディスクリプタの読み書きをしているということがわかって勉強になった。
この part はLinuxのシステムコールを多用するが、それぞれの解説は浅いので、コードを写経して動きをなんとなく理解するという感じになってしまった。深く理解するには別の書籍等が必要だと思う。
特に後半は説明が雑になってくるので、それぞれを深く学ぶことはできないが、自分のような非情報系の専攻の人にとっては良い本だと思う。 難点は分量で、(英語で読んだので)1000ページくらいあって、読むのに3ヶ月くらいかかった。しかし、時間をかけただけの価値はあったと思う。
この本を読む前の自分のこと