環境
当方の環境は以下である。
zig version: 0.16.0-dev.2960+ce1f7136a
Windows 11 + x86_64 + wsl2 + ubuntu24.04 + zsh
基本的なコマンド
ビルとシステムの公式学習サイトによると、基本的なコマンドとして以下が実装されている。例としてソースファイル名をhoge.zigとする。
zig build-exe hoge.zig
->ソースかオブジェクトから実行ファイル(hoge)を生成するzig build-lib hoge.zig
->ソースかオブジェクトから静的ライブラリ(libhoge.a)を生成するzig build-obj hoge.zig
->ソースかオブジェクトからオブジェクト(hoge.o)を生成するzig test hoge.zig
->単体テストを実行する
尚、静的ライブラリの拡張子.aは複数のオブジェクトをまとめたアーカイブ(archive)であることから来ている。
また、大規模プロジェクトなどで複雑になっていくビルド手順を一括で実行するためのZig Build Systemが提供されており、build.zigを用意しzig buildコマンドで実行できる。makefileとmakeのイメージにゅんちゅ。
zig build-exe
本稿ではzig build-exeについて確認する。まず、ソースファイルを作成する。
zig: hello.zig
const std = @import("std");
pub fn main(init: std.process.Init) !void {
try std.Io.File.stdout().writeStreamingAll(init.io, "hello, world\n");
}
脱線するが、zig公式ドキュメントでは「Hello, World!」という綴りとなっている。しかし、当方はK&RのThe C Programming Language(1978)に記載されている「hello, world」を採用することにしている。何となく由緒正しそうでかっこいいにゅんちゅ。
話を戻して、zig build-exeによるコンパイルと実行ファイルの実行方法は以下である。
zsh
% zig build-exe hello.zig
% ./hello
hello, world
%
build modeと呼ばれる4種類の最適化
上述の基本的なコマンド全て、オプションで以下4種類の最適化を指定することができる。
| build mode | optimization | safety checks | compilation speed | runtime performance | binary size |
|---|---|---|---|---|---|
| Debug(default) | off | on | fast | slow | large |
| ReleaseFast | for performance | off | slow | fast | large |
| ReleaseSafe | for performance | on | slow | medium | large |
| ReleaseSmall | for small binary | off | slow | medium | small |
実際に比較してみる。生成する実行ファイル名は--nameオプションで指定できる。コンパイル速度等も比較したいため、\timeコマンドを使用する。また、二回連続で一連のコマンドを実行することにより、ページキャッシュを活用してinputs(ブロックI/OのI)を0に揃える。
zsh
% \time zig build-exe hello.zig
0.48user 0.10system 0:00.26elapsed 222%CPU (0avgtext+0avgdata 135520maxresident)k
0inputs+17680outputs (0major+25565minor)pagefaults 0swaps
% \time zig build-exe -O Debug --name hello_debug hello.zig
0.46user 0.13system 0:00.26elapsed 225%CPU (0avgtext+0avgdata 136856maxresident)k
0inputs+17680outputs (0major+25874minor)pagefaults 0swaps
% \time zig build-exe -O ReleaseFast --name hello_releasefast hello.zig
8.99user 0.56system 0:09.54elapsed 100%CPU (0avgtext+0avgdata 408744maxresident)k
0inputs+17280outputs (44major+273151minor)pagefaults 0swaps
% \time zig build-exe -O ReleaseSafe --name hello_releasesafe hello.zig
9.05user 0.50system 0:09.54elapsed 100%CPU (0avgtext+0avgdata 416136maxresident)k
0inputs+16424outputs (42major+283952minor)pagefaults 0swaps
% \time zig build-exe -O ReleaseSmall --name hello_releasesmall hello.zig
1.54user 0.13system 0:01.64elapsed 101%CPU (0avgtext+0avgdata 146244maxresident)k
0inputs+728outputs (3major+33325minor)pagefaults 0swaps
% ls -Fl
total 25148
-rwxr-xr-x 1 hoge hoge 10554338 Apr 14 02:13 hello*
-rw-r--r-- 1 hoge hoge 150 Apr 12 13:26 hello.zig
-rwxr-xr-x 1 hoge hoge 10554338 Apr 14 02:13 hello_debug*
-rwxr-xr-x 1 hoge hoge 3843488 Apr 14 02:13 hello_releasefast*
-rwxr-xr-x 1 hoge hoge 3638304 Apr 14 02:13 hello_releasesafe*
-rwxr-xr-x 1 hoge hoge 147152 Apr 14 02:13 hello_releasesmall*
%
指定無しとDebug指定が同一処理であることを確認できた。また本稿の例では、ReleaseFastとReleaseSafeはDebugに対してコンパイルに約37倍の時間が掛かっており、compilation speedのslowはかなりスローなことが分かる。一方、同じくslowと説明があったReleaseSmallについては、Debugに対してコンパイルに掛かった時間は約7倍であり、ReleaseFastとReleaseSafeよりはコンパイル速度が速いことが見受けられる。バイナリサイズについては、ReleaseFastに対しRleaseSmallでは約4%まで小さくなっており、最適化を振り切るとここまで大きく変わるのかと驚いた。実行時間についても比較したいが、hello worldでは比較にならないので本稿では断念する。また、safety on/offに関する挙動の違いも検証したいが、長くなりそうなのでそれはまた別の投稿で実施したいにゅんちゅ。

