Scalaでは`private[this]`を積極的に使うべきなのか

どうもukaznilです。
最近早起きにハマっていると前回の記事でも書いた気がしますが,無事に継続中です。休みの日でも5時に起きてまだ暗いとちょっとテンション上がります。子供心ですね。もう26歳ですけど。

さて,最近は勉強しないとなぁと感じさせられることが非常に多くて焦るばかりなのですが,その対策として「どんなに小さな事でも1日1個は新しい知識を身につける」というノルマを自分に課してみようと思い立ちました。ここでいう「知識」は「経験則」というよりも,「今までなんとなく分かっていたけどいざ説明すると難しい」もしくは「今まで触れてこなかった体系的な知識」のいずれかのつもりです。

で,せっかく早起きなので余裕があれば(たぶん土日限定ですが),それを記事にしてみるのもいいライフハックかなあと。

そんなわけで短めですが記事を書いてみます。

Scalaにおけるprivate[this]

今まで主に(Android)JavaやKotlinに触れてきた私ですが,大学院の研究の過程で同じくJVM言語であるScalaにも1年超触れてきました。
やっぱりpureなJavaだと手が届かない部分にまでリーチできるScalaは,そのパワフルさが売りで機械学習などでもよく使われていますね。
ただその分細かい言語仕様は複雑で,なかなか全容を理解することは難しいです(そもそも私レベルだとJavaですらThread周りはよくわかりません。これは次回以降の宿題)。

で,ちょっと調べ物をしていたら以下のページを見つけました。

Scalaにおける細かい最適化のプラクティス - xuwei-k's blog
列挙順自体はとくに意味ありません。あと「どの最適化がどのくらい速くなるのか?」を詳細に計ったことはないですし、「原理的にこうなってるから(ry」というのを説明するに過ぎません。中には「JITで無意味になるようなどうでもいい細かすぎること」も書いてありま...

この中の項目1・「private[this]をつかえ」に今回はフォーカスを当ててみます。引用しますね。

scalaのvalやvarは、private[this]にしたときのみ、直接のフィールドアクセスになります(それ以外ではメソッド呼び出し)。シングルトンのobjectの場合も同様です。private[this]をつけられる場合はできるだけつけましょう

え。private[this]した方が速いの? これは目から鱗でした。でも正直マユツバなので検証してみましょうか。

検証コード

後述しますが,訳あってScalaのバージョンは2.11.11(JDK 7u80)です。IntelliJ IDEAで検証しました。

やってることは単純で,private valinput1と,private[this] valinput2を大量(=Int.MaxValue回)に呼び出して計測しているだけです。

結果はこんな感じになりました(実行毎に微妙に値が異なります)。

結構違いますね!! Java7互換のScala2.11.xだからかもしれませんが,なかなか無視できないくらいの差が出てきました。

クラスファイルはどうなってる?

先ほどの引用にもあったように,本当に

Scalaのvalやvarは、private[this]にしたときのみ、直接のフィールドアクセスになります(それ以外ではメソッド呼び出し)。

になっているのでしょうか。
生成したクラスファイルをデコンパイルしてみます。

まずはみんな大好き jad でデコンパイルします。
jad持っていない人は,以下のサイトからダウンロードするか,mac OS使いであればhomebrewを使ってbrew cask install jadでもインストールできます。

大事なのは上のTester.scalaなので,それだけ掲載します。

ハイライトしてある29-31行目と,58-60行目を見ると,それぞれ

になっているのがわかります。16-18行目には対応するinput1()メソッドが生成されていますね。
確かに,private[this]にしたときは直接のフィールドアクセスになっていました。なにこれ目から鱗(2回目)。

でもこれくらいの最適化はコンパイラがやってくれてもいいのなー。

おまけ(Scala2.12.x系の場合)

上の検証ではScala2.11.11を用いたのですが,なんで最新の2.12.xじゃないの? と。
当然最初はそれで試していたのですが,jadがうまく動かなくてですね……。慣れないデコンパイルとかするもんじゃないですね……。

ちなみに,まったく同じコードでScala2.12.3(JDK 8u144)を使うと,結果はこんな感じになります。

おー。結構速くなってますね。特にprivate val2597 msec → 1152 msec と頑張ってます。
jadできなかったのでクラスファイル見られていませんが,恐らく同じ,なのかな……?

おわりに

今日は早起きで時間があったので,珍しくコードを交えて検証記事を書いてみました。
検証・記事執筆で1時間ちょっとくらいなので,土日の朝の体操にはうってつけかもしれません。
(といいつつ記事まで続くかどうかは微妙なところ……笑)

Share this:

コメントを残す

メールアドレスが公開されることはありません。

ABOUTこの記事をかいた人

東京大学大学院修士号(情報理工学)取得。
Androidアプリ開発者6年目。出没地域は映画館,本屋,勉強会。御朱印の集印がマイブーム。思い出深い神社は埼玉県・三峯神社と滋賀県・多賀大社。