Go言語の最新リリースであるGo 1.15は、ツールチェーン、ランタイム、コアライブラリの改善が中心のリリースだ。リンカや小オブジェクトのアロケーション改善に加えて、X.509 CommonName
が廃止され、新たにtzdata
組み込みパッケージなどがサポートされた。
Goリンカは、その目標をメモリおよびCPU時間の使用量削減に変えるとともに、堅牢性やメンテナンス性も改善されている。
代表的な大規模Goプログラムセットで、amd64アーキテクチャ上で動作するELFベースのOS(Linux、FreeBSD、NetBSD、OpenBSD、Dragonfly、Solaris)において、平均で20パーセントの高速化と30パーセントのメモリ使用量削減を確認しています。ただし、アーキテクチャとOSの組み合わせによっては、改善度がこれより低くなる可能性はあります。
この改善は、オブジェクトファイル形式の再設計と、リンカの内部並行性の向上によって実現された。これらの変更は、実を言うと、Goを使用した大規模システム構築におけるメリットを主目的としてGoリンカを現代化するための、複数リリースにわたる改善成果の最初のものに過ぎない。事実としてGoのリンカは、元々Cで書かれていたものを半自動でGo文法に変換したのであり、Goツールチェーン用に最適化されたコンポーネントと言えるものではなかった。しかも、言語やそれによって構築されるシステムが成長していったにも関わらず、リンカの設計は相変わらずそのままだったのだ。
Goには非常に効率的なリンクアルゴリズムに対応可能な機能があるのですが、現時点ではそれらのアドバンテージは利用されていません。一方で、Goはオブジェクトファイルフォーマットも独自にコントロールしているので、コンパイラ、オブジェクトフォーマット、リンカを共通設計して革新するチャンスが与えられているのです。
Go 1.15コンパイラでは、GC関連のメタデータを廃止することによって、生成されるバイナリのサイズが小さくなった。Go 1.14に比較すると、約5パーセントの削減が実現されている。さらにunsafe
なポインタをuinptr
に変換する場合に、コンパイラが従来より厳格な安全ルールを用いるようになったため、複数チェーンの変換を使用している既存コードは修正する必要がある。
ランタイムの面では、コア数の多いシステムでの小さなオブジェクトのアロケート方法が改善されると同時に、最悪時のレイテンシも低減された。小さな整数値をインターフェース値に変換する際のメモリアロケーションも不要になった。
Goコアライブラリの変更に関しては、サブジェクト代替名(SAN)が存在しない場合の、X.509証明書のCommonName
フィールドの処理方法が変更され、デフォルトではホスト名として扱われなくなった。ただしGODEBUG
環境変数にx509ignoreCN=0
という値をアサインすることで、再度有効にすることも可能である。
さらにGo 1.15には、新たにtime/tzdata
パッケージが含まれていて、timezoneデータベースをプログラムに埋め込むことが可能になっている。これにより、ローカルシステム上でtimezoneデータベースが使用できない場合でも、800KBのバイナリサイズ増加というコストはあるものの、プログラムがtimezone情報を検索できるようになる。
Go 1.15には、ここでは紹介されていない変更や改善も多数含まれているので、オフィシャルリリースノートでその内容を確認してほしい。