Java : 「.」のコストとfor文の最適化

http://dev.ariel-networks.com/Members/dev/300cfor-6587-2-0300d304b3089306e30e130bf30e130c330bb30fcより

for (int i=0; i < args.length; ++i) {

という書き方よりも

for (int i=0, len = args.length; i < len; ++i) {

という書き方の方が早いよという話で、これが最適化が掛からないのが悲しいという件。
で、さらに話は進んで、

args.length
args.length()

の2つのケースがあって、1つ目はそれほど遅くならないけれど、2つ目は遅くなるよとかそんな話。

      • -

うーん・・・。
メソッド呼び出しである

for (int i=0, len = args.length(); i < len; ++i) {

for (int i=0; i < args.length(); ++i) {

に最適化が掛からないのは当然だし、掛かったら困るじゃないですか。だって、Javaのメソッドは副作用があるかどうかは外形からは分からないような仕様なんだから、字面上で呼び出した回数だけ、実際に実行時に呼び出されなければ、おかしなことが起こってしまいます。
さらに、フィールドアクセスである

for (int i=0, len = args.length; i < len; ++i) {

for (int i=0; i < args.length; ++i) {

に最適化が掛かるのは一見問題なさそうですが、argsがfinal宣言されていなければ、for文の中でargs変数の指す対象が変化する可能性があるので、やはりそのように最適化を掛けるのは難しそう。プログラムを意味的に解析してやれば(特に、argsがローカル変数なら)可能だとは思いますが、その文コンパイラの仕事が増えて、コンパイル時間が増大することを考えると、コストに見合うのかなとちょっと思ってしまいます。

      • -

Delphiみたいに、ループ変数の終了境界は、ループに入る前に評価してしまう仕様にするという割り切りもありますが、あれはあれで面倒くさいときもあるので、Javaの(そしてCの)for文はあれでいいんじゃないですかねぇ。
そんなに気になるなら、final付けろ*1ということで、finalが面倒なら関数型言語(特に、Clean)をおすすめします。

*1:finalがついている時に、最適化が掛かるかどうかは未確認です。