cloudfoundry/java-buildpack-memory-calculatorをベースに自動でクラスファイルを数えてJVMのメモリ周りのオプションを吐いてくれるツールをGoで再実装した
これは出落ち感があるんですが 既にmaking/memory-calculator-cnbというものがあり UberJarやディレクトリに入ってるクラスファイルを再帰的に、cloudfoundry/java-buildpack-memory-calculatorを使ってJVMオプションを吐いてくれます。
というわけで、今回書いたツールは、making/memory-calculator-cnbに似たツールを再実装した話になります。
ディレクトリもサポートするぞーと思って一通り書いた後に この記事を書こうとして、making/memory-calculator-cnbの実装をちゃんと読んだら ディレクトリもサポートしていることに気が付きました・・・。
なので、実装している機能としてはほぼ一緒のものになります。
追記: cloudfoundry/java-buildpackの実装を参考に 弄ったので、making/memory-calculator-cnbの実装からは微妙に変わりました
追記: 作ったツールのリンクを貼っていませんでした。 貼っておきます。
はじめに
cloudfoundry/java-buildpack-memory-calculatorでは、loaded-class-countというパラメータがあります。 読み込むクラスファイル数を渡すことで自動でJVMのオプションを吐いてくれます。(他にも必要なパラメータがあるけど)
しかし、元々のcloudfoundry/java-buildpack-memory-calculatorでは、クラスファイルを数えてくれる機能などはありません。 自分でクラスファイル数を数える必要があります。これは面倒です。
そこで、Jarやディレクトリを再帰的に読み込んでクラスファイルを数えて、cloudfoundry/java-buildpack-memory-calculatorを使って JVMオプションを出力してくれたら嬉しいなぁと思って、wreulicke/emcを書きました。
が、先ほども言った通りmaking/memory-calculator-cnbで全く同じものがJavaで実装されています。
変わった点としてはGoで実装したぐらいです。
追記: cloudfoundry/java-buildpackの実装を参考に 弄ったので、making/memory-calculator-cnbの実装からは微妙に変わりました。
インストール方法
インストール方法を書いてなかったので追記しました。 GitHubにReleaseしたバイナリを置いてあるので そこから取ってきて必要があればPATHに入れてください。
# MacOS curl -L https://github.com/wreulicke/emc/releases/download/v0.0.1/emc_0.0.1_darwin_amd64 -o /usr/local/bin/emc # Linux curl -L https://github.com/wreulicke/emc/releases/download/v0.0.1/emc_0.0.1_linux_amd64 -o /usr/local/bin/emc # Windows curl -L https://github.com/wreulicke/emc/releases/download/v0.0.1/emc_0.0.1_windows_amd64.exe -o <path-directory>/emc.exe
使い方
まずはヘルプを見てみましょう。 cloudfoundry/java-buildpack-memory-calculatorとほぼ同じパラメータを持っています。
$ emc --help usage: emc [<flags>] [<jarOrDirectory>] Enhanced java memory calculator Flags: --help Show context-sensitive help (also try --help-long and --help-man). -v, --verbose Verbose --total-memory=TOTAL-MEMORY Total memory. Required if is not limited by cgroup --loaded-class-count=LOADED-CLASS-COUNT Loaded class count --thread-count=250 thread count --java-options="" JVM Options --head-room=0 Percentage of total memory available which will be left unallocated to cover JVM overhead --java-version=11 Java version Args: [<jarOrDirectory>] jar or directory
ディレクトリを指定する場合は以下のようなイメージです。
$ emc --total-memory 1G <path/to/directory> -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=14447K -XX:ReservedCodeCacheSize=240M -Xmx266128K
また、jarを指定することも出来ます。もちろん、UberJarのような Jarの中にJarが入ったようなものでもサポートしています。
$ emc --total-memory 1G <path/to/your.jar> -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=14447K -XX:ReservedCodeCacheSize=240M -Xmx266128K
まとめ
完全にmaking/memory-calculator-cnbとほぼ一緒の実装になりましたが Goで実装したので、ある程度バイナリを使い回しやすいのかなと思っています。
終わり。saracen/walker が便利だった。
追記
ちょっとcloudfoundry/java-buildpackの実装を読んでいたら 標準ライブラリを読んでいたり、0.35という割合(多分、jarにあっても読まないファイルがあることを考慮している)を掛けていたりするので そちらに参考にして、標準ライブラリのクラスも加えた上で、0.35を掛けて 読み込むクラス数とするようにした。
微妙にmaking/memory-calculator-cnbから変わった。
実際にカウントしてみて気になったんだけど、java-buildpackの標準ライブラリのファイル数間違えてない?
Why does java-buildpack use 42215 as stdlib class count?
— wreulicke (@wreulicke) 2020年2月7日
In my environment, I seems that stdlib class count is 33615...
Java 9 Class Count · cloudfoundry/java-buildpack@82aae94 https://t.co/53q83tvzZm pic.twitter.com/QydMCSusrr