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の実装からは微妙に変わりました

追記: 作ったツールのリンクを貼っていませんでした。 貼っておきます。

github.com

はじめに

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の標準ライブラリのファイル数間違えてない?