性能とはなにか【『効率的な Go』読書会 初回】
冬の間忙しくてできなかった読書会への参加を再開することにした。
「横浜Go読書会」とあって田舎暮らしの私としては躊躇するところではあったが主催の柴田芳樹さんより「全国から参加可能」と言っていただけたので参加することに決めた。
題材となる書籍はこれ。
- 効率的なGo ―データ指向によるGoアプリケーションの性能最適化
- Bartłomiej Płotka (著), 山口 能迪 (翻訳)
- オライリー・ジャパン 2024-02-24
- 単行本(ソフトカバー)
- 4814400535 (ASIN), 9784814400539 (EAN), 4814400535 (ISBN)
- 評価
版元で Ebook を買える。Go言語のリファレンス本ではない。フトウェア工学,プログラミング(の考え方)を学ぶ教科書的な位置づけかなぁ。
版元が O’Reilly Japan ということで PDF で購入した。
タイトルを見たとき「ついに Effective Go を冠する本が出たのか」と思ったが翻訳者の方に「“Efficient Go” だよ」と指摘していただいた恥ずかしい過去は内緒である。
普通は本を買ったら最低でも流し読みくらいをしておくものだけど,これを買った2月頃はホンマに忙しくてねぇ。 目次くらいしか眺めてなかった。 まぁ読書会で読むし,と後回しにしてたら結局初見で読書会に望むことになってしまった。 反省。
『効率的な Go』は11章で構成されていて500ページちょっとというボリューム。 読書会では読み終わるまで1年くらいかかるかなぁという見通しだった。 1回目の今回は都合で時間短めだったこともあり,序文と1章の途中まで。
読み始めた最初の感想は「講釈が長い!」だった。 Go のコードは殆ど出てこないし。
読書会のあとで後ろの章をさっくり眺めてみたが,コードは少なめで地の文章が多い。 なので,よくあるリファレンス本と思って読むと面食らうかもしれない。 どっちかというとソフトウェア工学,プログラミング(の考え方)を学ぶ教科書的な位置づけかなぁ。 その教材としてのプログラミング言語として Go が選ばれているという感じ。 実際に序文でも
最適化の考え方やオブザーバビリティパターンを示すためにGoを例題言語として使っていますが、本書の11 章のうち8章は言語に中立的に書かれています。Java、C#、Scala、Python、C++、Rust、Haskellなど、他の言語で書かれたソフトウェアを改善するために、同じテクニックを使えます。
と書かれている。 なので,この本の内容を Go 以外の言語で応用するにはどうすればいいか考えながら読むのも面白いかもしれない。
そういえば「訳者まえがき」には
私が直近で翻訳に携わった『オブザーバビリティ・エンジニアリング』(2023、オライリー・ジャパン、ISBN9784814400126)、『SLO サービスレベル目標』(2023、オライリー・ジャパン、ISBN9784814400348)の2冊に続いて、本書が加わることで、システムの性能改善というテーマにおいてマクロからミクロまで、全体の理解を深められる書籍が揃ったからです。したがって先の2冊を併せて読むことで、広い視点を保ったまま、プログラムの性能改善に取り組む意味が見えてくると思います。
と書かれている。 この辺も読んでおくといいかも。
では,1章の前半で刺さったフレーズをつまみ食いしてみよう。
よく言われるように、「完璧は善の敵(Perfect is the enemy of good、https://oreil.ly/OogZF)」ですが、まずはそのバランスの取れた善を見つけなければなりません。
これは個人的に
理学は、真理の探究であり、工学は善の実現である。そして、藝術は美の表現である--これで所謂「真美善」が揃う
を座右の銘のひとつとしている私としては気になるフレーズである。
ちなみに https://oreil.ly/OogZF
は Wikipedia へのリンクになっていて,そのバリエーションとして
“If you never miss a plane, you’re spending too much time at the airport”
というフレーズがあって笑ってしまった。他に Donald Knuth 博士の
“Premature optimization is the root of all evil”
も紹介されていたが,これは『効率的な Go』でも言及されている。
しかし、この名言はずいぶん前になされたものです。過去から一般的なプログラミングについて多くを学ぶことができる一方で、1974年から大幅に改善されたことも多くあります。たとえば、当時はリスト1-5に紹介されているように、変数名に変数の型に関する情報を追加することが一般的でした。
「リスト1-5」ってのがこれ
type structSystem struct { sliceU32Numbers []uint32 bCharacter byte f64Ratio float64 }
いわゆるハンガリアン記法ってやつですな。
当時はコンパイラーや統合開発環境(IDE)があまり成熟していなかったので、ハンガリアン記法が便利でした。しかし現在では、IDEやGitHubのようなリポジトリサイトでも、変数にカーソルを合わせるとすぐにその型を認識できるようになりました。数ミリ秒で変数の定義にたどり着き、解説を読み、すべての呼び出しと変更を見つけられます。賢いコードの提案、高度なハイライト、1990 年代半ばに開発されたオブジェクト指向プログラミングの優位性により、実用的な可読性に大きな影響を与えることなく、機能や効率の最適化(複雑化)を追加できるツールを手に入れました。
最近では、IDEの機能に対応しやすいようにコードを書くことが推奨されていることは、特筆に値するでしょう。たとえば、コード構造は「連結」グラフ(https://oreil.ly/mFzH9)であるべきです。これは、IDE が支援できる方法で関数を接続することを意味します。動的ディスパッチ、コードインジェクション、遅延読み込みは、これらの機能を無効にするので、厳密に必要でない限り避けるべきです。
こういった感じにツールの助け等によってコードに対する認知負荷が変わってきているため「性能の最適化」も昔とは変わってきている,ということらしい。
じゃあ,そもそも「性能(performance)」って何? って話になる。 この辺の話が今回読んだ中で一番面白かった。
私の経験では、多くの人がソフトウェア開発において性能(パフォーマンス)という言葉を速度(スピード)の代名詞と考えています。他の人々にとっては、この言葉の本来の定義である実行の全体的な質を意味します 。この現象は「意味拡散(semantic diffusion、https://oreil.ly/Qx9Ft)」と呼ばれることもあり、ある言葉がより大きな集団によって、本来持っていた意味と異なる意味で使われ始めるときに起こります。
結論から言うと、性能とは少なくともこの3つの要素の組み合わせです。
\[ 性能 = ( 精度 \times 効率 \times 速度 ) \]
ここで性能は単にソフトウェアの機能を指すものではないというのが重要なポイント1。 日々要件が変わるソフトウェア開発においては如何にして変化をプロセスに組み込み小刻みにイテレーションを回していくかが重要になる。
たとえば、RockstarGamesが人気ゲーム「グランド・セフト・オートV」を開発するのに5年の歳月と250人のエンジニアを要し、その費用は1億3750万ドルと推定されて(https://oreil.ly/0CRW2)います。また、Appleは、実用的で商品化されたOSを作るために、2001年にmacOSを初めてリリースするまでに5億ドル(https://oreil.ly/hQhiv)をはるかに超える資金を費やさなければなりませんでした。
故に1章の「ソフトウェア効率性が重要」という見出しになるわけだ。
…という感じで読み進めていくことになりそうだ。 次回の読書会の感想を書くかどうかはわからないけど(笑)
参考
- Go言語による並行処理
- Katherine Cox-Buday (著), 山口 能迪 (翻訳)
- オライリージャパン 2018-10-26
- 単行本(ソフトカバー)
- 4873118468 (ASIN), 9784873118468 (EAN), 4873118468 (ISBN)
- 評価
- プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- Alan A.A. Donovan (著), Brian W. Kernighan (著), 柴田 芳樹 (翻訳)
- 丸善出版 2016-06-20
- 単行本(ソフトカバー)
- 4621300253 (ASIN), 9784621300251 (EAN), 4621300253 (ISBN)
- 評価
著者のひとりは(あの「バイブル」とも呼ばれる)通称 “K&R” の K のほうである。この本は Go 言語の教科書と言ってもいいだろう。と思ったら絶版状態らしい(2025-01 現在)。復刊を望む!