先週の社内勉強会の話。IntegerをtoString()すると、StringのvalueOfに行って、結局、Integer.toString(int i)に戻ってくるんだったら、始めからtoString()の中でInteger.toString(i)を呼ばないのは無駄だね~、という話題もあったのだけど、それ以上に疑問に思った話題がシフト演算子と算術演算子で書いたときのパフォーマンス。まぁ、誤差っていえば誤差のような気もするのだけど、シフト演算子で書いたときの微妙な遅さ。比較に使ったコードは以下のような感じ。
package com.marevol.test; public class App { public static int dummy1 = 0; public static int dummy2 = 0; public static void main(String[] args) { long max = 100000000L; int value = 10; // compile code dynamically for (int i = 0; i < 5; i++) { pattern1(max, value); pattern2(max, value); } System.out.println("max=" + max); long p1 = 0; long p2 = 0; for (int i = 0; i < 5; i++) { p1 += pattern1(max, value); p2 += pattern2(max, value); } System.out.println("Time(<<): " + p1 + " (" + dummy1 + ")"); System.out.println("Time(*X): " + p2 + " (" + dummy2 + ")"); } public static long pattern1(long count, int num) { long startTime = System.currentTimeMillis(); int c = 0; for (long i = 0; i < count; i++) { // c = (num << 6) + (num << 5) + (num << 2); c = num << 1; // c = num >> 1; } long endTime = System.currentTimeMillis(); dummy1 = c; return endTime - startTime; } public static long pattern2(long count, int num) { long startTime = System.currentTimeMillis(); int c = 0; for (long i = 0; i < count; i++) { // c = num * 100; c = num * 2; // c = num / 2; } long endTime = System.currentTimeMillis(); dummy2 = c; return endTime - startTime; } }
これを実行すると以下みたいな感じ。
$ java -version java version "1.6.0_06" Java(TM) SE Runtime Environment (build 1.6.0_06-b02) Java HotSpot(TM) 64-Bit Server VM (build 10.0-b22, mixed mode) $ uname -r -m -v -s Linux 2.6.18-53.1.19.el5 #1 SMP Wed May 7 08:22:53 EDT 2008 x86_64 $ cat /proc/cpuinfo |grep "model name" model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz $ java -cp target/classes/ com.marevol.test.App max=100000000 Time(<<): 547 (20) Time(*X): 543 (20)
これから思うに、シフト演算でがんばって計算しても意味ない気が・・・。微妙な差が気になるけど、JVMが実行しているコード見ないとわからん気も。