雑賀 力王オフィシャルサイト

Abby CTO 雑賀 力王のオフィシャルサイトです

Clojure (Java) はやはり速かったという話

Clojure (Java) はやはり速かったという話

あまりにも遅すぎなのでは?と思ったので調べたらやはり計測方法に問題があっ たみたい。

Java がこんなに遅いわけない。

遅かった原因

いつも通り nrepl 経由で適当に実行していたのが原因。

leiningen から nrepl を立ち上げていたのだが、以下を見れば遅い理由がわかる。

java -client -Xbootclasspath/a:/home/ma2/.lein/self-installs/leiningen-2.3.3-standalone.jar -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Dfile.encoding=UTF-8 -Dmaven.wagon.http.ssl.easy=false -Dleiningen.original.pwd=/home/ma2 -Dleiningen.script=/home/ma2/bin/lein -classpath /home/ma2/.clojure:/home/ma2/.lein/self-installs/leiningen-2.3.3-standalone.jar clojure.main -m leiningen.core.main repl :headless :port 60000

-client オプション久々に見た!

leiningen は前から起動がクソ遅いと文句を言われていたので jvm のオプションを指定している。

起動速度をあげるために以下のオプションで起動している。

  • -client

  • -XX:+TieredCompilation

  • -XX:TieredStopAtLevel=1

oh …

実行速度が遅くて当たり前である。

lein スクリプト内

...

export LEIN_JVM_OPTS="${LEIN_JVM_OPTS-"-XX:+TieredCompilation -XX:TieredStopAtLevel=1"}"

...

export TRAMPOLINE_FILE
"$LEIN_JAVA_CMD" -client \
    "${BOOTCLASSPATH[@]}" \
    $LEIN_JVM_OPTS \
    -Dfile.encoding=UTF-8 \
    -Dmaven.wagon.http.ssl.easy=false \
    -Dleiningen.original.pwd="$ORIGINAL_PWD" \
    -Dleiningen.script="$SCRIPT" \
    -classpath "$CLASSPATH" \

がっつり固定で書かれている…

grench から起動すればこんなの気にしなくていいので -server モードで起動するようにすべきである。

server モード で計測

lein スクリプトを修正して以下のオプションで立ちあげてみる。

java -server -Xbootclasspath/a:/home/ma2/.lein/self-installs/leiningen-2.3.3-standalone.jar -Xms512m -Xmx1024m -Dfile.encoding=UTF-8 -Dmaven.wagon.http.ssl.easy=false -Dleiningen.original.pwd=/home/ma2 -Dleiningen.script=/home/ma2/bin/lein -classpath /home/ma2/.clojure:/home/ma2/.lein/self-installs/leiningen-2.3.3-standalone.jar clojure.main -m leiningen.core.main repl :headless :port 60000

計測してみよう。

λ grench eval '(time (reduce unchecked-add (map unchecked-add (range 1000000) (range 1000000))))'
"Elapsed time: 366.023913 msecs"
999999000000

ほぼ Python と変わらないくらいになった。

僕のおんぼろ X200s だとこれぐらいですが、会社の i7 搭載マシンだと Python より速くなります。

まとめ

パフォーマンスを計測する場合、leiningen 使うとダメです! nrepl 経由で楽せずちゃんと測りましょう!