TSS is all hyped up about Cameron's performance test JVM vs CLR (wow big headlines all for nothing).
On the surface it looks like java it a winner here, so with the risk of getting flamed here, I say the performance test sux and it sux big time. this is what happens if you play with things you don't understand.
the code looks pretty simply, but what Cameron didn't cared about was Boxing and Capacity. Ignoring boxing/unboxing, can slow your program down. period. Beauty and the beast in the CLR.
value types, such as int's requires boxing in order to be treated as objects, so looking at his code
list.Add(new Person(i, "John " + i));
take a look at the IL code :
IL_0011: ldstr "John " IL_0016: ldloc.1 IL_0017: box [mscorlib]System.Int32 <-- boxing takes place here IL_001c: call string [mscorlib]System.String::Concat(object, <-- object) <-- IL_0021: newobj instance void people.Person::.ctor(int32, string) IL_0026: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
no boxing occurs here:
list.Add(new Person(i, "John " + i.ToString()));
IL code:
IL_001c: ldstr "John " IL_0021: ldloca.s V_1 IL_0023: call instance string [mscorlib]System.Int32::ToString() IL_0028: call string [mscorlib]System.String::Concat(string, string) IL_002d: newobj instance void people.Person::.ctor(int32, string) IL_0032: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
also notice the String::Concat here.
another optimization is calling the ArrayList.Capacity, this will reallocated the internal array, thereby preventing this from happening during the loop.
also in his 'test' method which gets called in a loop:
DateTime finish = DateTime.Now; Console.WriteLine("Total time for iteration " + iIter + ": " + (finish - start));
IL code: IL_004d: box [mscorlib]System.TimeSpan <--- boxing. IL_0052: stelem.ref IL_0053: ldloc.3 IL_0054: call string [mscorlib]System.String::Concat(object[]) <-- IL_0059: call void [mscorlib]System.Console::WriteLine(string) IL_005e: ret } // end of method ManyPeople::test actually boxing takes place with iIter value type also. IL code not shown, I assume you believe me.
a simple rewrite and no boxing takes place:
DateTime finish = DateTime.Now; TimeSpan dt = finish - start; Console.WriteLine("Total time for iteration " + iIter.ToString() + ": " + dt.ToString());
so here are my results, funny it shows a different picture, yeah go figure :-)
ladies first:
C:perfjavaperfclasses>java ManyPeople Total time for iteration 0: 5417 Total time for iteration 1: 5298 Total time for iteration 2: 5298 Total time for iteration 3: 5297 Total time for iteration 4: 5288 Total time for iteration 5: 5297 Total time for iteration 6: 5298
C:perfjavaperfclasses>java -server -Xms24m -Xmx24m ManyPeople Total time for iteration 0: 4467 Total time for iteration 1: 4316 Total time for iteration 2: 4306 Total time for iteration 3: 4326 Total time for iteration 4: 4307 Total time for iteration 5: 4326 Total time for iteration 6: 4316
C:perfjavaperfclasses>java -server -Xms128m -Xmx128m ManyPeople Total time for iteration 0: 3616 Total time for iteration 1: 3364 Total time for iteration 2: 3445 Total time for iteration 3: 3405 Total time for iteration 4: 3445 Total time for iteration 5: 3445 Total time for iteration 6: 3345
ok the hotspot does a better job from time to time.
and now for the C# version with no boxing and use of Capacity.
C:perfpeoplepeoplebinRelease>people Total time for iteration 0: 00:00:03.1945936 Total time for iteration 1: 00:00:02.9542480 Total time for iteration 2: 00:00:03.0844352 Total time for iteration 3: 00:00:03.1244928 Total time for iteration 4: 00:00:03.1545360 Total time for iteration 5: 00:00:03.0443776 Total time for iteration 6: 00:00:02.7840032
hmm close race, but far from Cameron's results.
actually I tried to ngen.exe on my code, is showed this:
C:perfpeoplepeoplebinRelease>people Total time for iteration 0: 00:00:03.1044640 Total time for iteration 1: 00:00:02.9141904 Total time for iteration 2: 00:00:03.1845792 Total time for iteration 3: 00:00:03.4048960 Total time for iteration 4: 00:00:03.1244928 Total time for iteration 5: 00:00:03.3748528 Total time for iteration 6: 00:00:03.1244928
but if you rewrite his 'Average' method
Person[] p = new Person[100000]; for (Int32 i = 0; i < 100000; i++) p[i] = new Person(i, "John " + i.ToString()); //no boxing now
long silly = 0;
for (Int32 x = 0; x < p.Length; x++) //get rid of the slow foreach silly += p[x].Id;
return silly / 100000;
it shows this result with ngen.exe
C:perfpeoplepeoplebinRelease>people Total time for iteration 0: 00:00:02.9342192 Total time for iteration 1: 00:00:03.0443776 Total time for iteration 2: 00:00:02.8941616 Total time for iteration 3: 00:00:02.8841472 Total time for iteration 4: 00:00:02.9842912 Total time for iteration 5: 00:00:02.9942912 Total time for iteration 6: 00:00:02.8841472
not spectacular faster. The CLR makes some pretty smart choices when loading and jit'ing the code.
now with boxing and no Capacity, it looks like this
C:perfpeoplepeoplebinRelease>people Total time for iteration 0: 00:00:04.3662784 Total time for iteration 1: 00:00:04.1259328 Total time for iteration 2: 00:00:04.6166384 Total time for iteration 3: 00:00:04.3863072 Total time for iteration 4: 00:00:04.1059040 Total time for iteration 5: 00:00:04.1459616 Total time for iteration 6: 00:00:04.0958896
you see the performance loss here. yeah baby.
how many times have TSS published crappy performance test so far ? way to many times imo.
funny thing happened I accidentally tried to compile the java code with vs.net until I saw it was the java code I was trying to compile...yeah the code does look awful lot alike, let's just sit down in a circle and smoke.
test was made on a 2,4 ghz notebook, running XP proff. 512 ram, using vs.net 2003 ver 1.1 and jdk 1.4.1_02.
peace man.
12:17:37 AM
|