Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Scala Native 0.5.7 が出た -- バイナリの動的依存が大幅に削減

Scala Native 0.5.7がリリースされた。

github.com

主要なアップデートはリリースノートに書かれているが、面白いと思ったので紹介する。

Scala Nativeとは(おさらい)

Scala Nativeとは、ScalaプロジェクトをLLVMを利用してバイナリにビルドするプロジェクト、コンパイラプラグイン群の総称である。

scala-native.org

Scala Nativeを使うことでScalaコードをそのままネイティブバイナリにできるし、静的バイナリを作ることも可能だ:

blog.3qe.us

ScalaコードをLLVMでコンパイルする都合、Javaライブラリ(JVMバイトコードになっている)に依存しているとコンパイルできないので注意。

バイナリ互換性

Scala Native 0.5.7は0.5系の全てのバイナリに対して後方互換だ(つまり、呼び出すことができる)が、バイナリ前方互換性がない。つまりScala Native 0.5.6のプログラムから0.5.7でビルドされたライブラリを呼び出せない。 必要に応じてリビルドが必要である。(Scala Nativeはまだメジャーバージョンが1に到達していないためこういうbreaking changesは割とある)

C++標準ライブラリへの依存が削減

Unix環境でScala Nativeにビルドする場合、これまでC++標準ライブラリに依存していた(動的リンクしていた)のだが、0.5.7からは依存不要になった。

実際にscala-cliを用いて確認したところ、確かに依存性が減っていた。

このようなテストコードを用意する:

//> using scala 3.6.3
//> using platform native

println("Hello, Scala Native!")

scala-cliを使ってバイナリにビルドする:

% scala-cli package -o "code056.out" --native-version=0.5.6 code.scala.sc
% scala-cli package -o "code057.out" --native-version=0.5.7 code.scala.sc

lddを使うとバイナリが動的依存しているライブラリを確認できる:

% ldd code056.out
        linux-vdso.so.1 (0x00007ffc14257000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3f34d75000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3f34d6f000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f3f34b8d000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3f34a3e000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3f34a23000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3f34831000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3f34dac000)

% ldd code057.out
        linux-vdso.so.1 (0x00007ffd3cd85000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ffaab754000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffaab74e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffaab55c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ffaab78b000)

libstdc++.soへの依存と、libm.soへの依存、libgcc_s.soへの依存が取れているのがわかる。

もともとScala Nativeは例外ハンドリングまわりでC++標準ライブラリに依存していたのだが、今回は例外ハンドリングに必要な最小限の処理を自前で実装したことにより依存が取れたとのこと。ただしLTO(Link Time Optimization)を有効化している場合とWindows環境でビルドした場合は引き続きC++標準ライブラリに依存する。これは未解決の問題が残っているため。

また嬉しい副作用としてStack Overflowエラーのハンドリングが改善し、これまではプログラムが終了するだけだったが検知してハンドルできるようになった。

ファイルサイズはちょっと太った。

% ls -lah
Permissions Size User      Date Modified Name
drwxr-xr-x     - windymelt 27  2月 00:29 .bsp/
drwxr-xr-x     - windymelt 27  2月 00:29 .scala-build/
.rw-r--r--    82 windymelt 27  2月 00:29 code.scala.sc
.rwxr-xr-x  1.2M windymelt 27  2月 00:35 code056.out*
.rwxr-xr-x  1.3M windymelt 27  2月 00:36 code057.out*

clasのvtableのレイアウトが最適化された

classをScala Native上で表現するためにvirtual tableを利用しているところ、これが改善されてバイナリサイズの削減が見込めるようだ。

github.com

The size of small binaries might slightly increase

とのことなので、数MiBレベルの元々小さいバイナリはやや大きくなり、数十MiBレベルの元々大きかったバイナリが恩恵を受けるようだ。もしかするとバイナリが太ったのはこれのせいかもしれない。

Java標準ライブラリの実装

JDK9以降に実装された標準ライブラリの数多くの処理がポートされた。

一例を挙げると、JDK11のString#linesが実装された:

github.com

SCALANATIVE_THREAD_STACK_SIZE が設定可能になった

環境変数 SCALANATIVE_THREAD_STACK_SIZE が設定可能になった。これはJVMの-Xssに対応し、スレッドのスタックサイズを設定できる。

LinuxでPIE (Position Independent Executables) に対応した

github.com

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?