dev@grizzly.java.net

Re: a question on enum performance

From: charlie hunt <charlie.hunt_at_sun.com>
Date: Wed, 12 Dec 2007 14:44:23 -0600

Writing micro-benchmarks for Java is very hard and is largely an art.

With a micro-benchmark like this you need to run the "code of interest"
long enough that it is sufficiently compiled by the JIT compiler prior
to collecting timing information, (use -XX:+PrintCompilation to tell you
if JIT compilation is happening during your measurement timestamps).
And, you should run the "code of interest" for about 5 or 10 seconds in
a timing interval. Although System.currentTimeMillis() returns
milli-seconds, the accuracy between calls to System.currentTimeMillis()
is not guaranteed to have milli-second accuracy. The same applies to
System.nanoTime(). And, on Linux, System.nanoTime() returns a nano
second value, but you will notice the trailing 3 digits are always 0
implying that its accuracy is at best a micro-second. We also don't know
if you are testing with -server or -client. These use totally different
approaches for producing optimized native code.

Micro-benchmark issues aside ... you realize you get better compile time
type checking with enums versus int? For that benefit alone I would
suggest using enums.

I'll further say that if you can show performance of using ints is
better than enums, IMO, it's a bug, i.e. -server and -client should do a
better job of optimizing for enums if it is indeed the case that ints
out perform enums.

charlie ...

Shing-Wai.Chan_at_Sun.COM wrote:
> Hi,
>
> From code review comments, there is a concern about
> the performance of using enum.
> I have try to measure this by myself (see attached programs)
> and see the following:
>
> elliptic: /home/swchan2/doc/grizzly > java EnumTest
> time for int[10] (ms): 0
> time for type[10] (ms): 1
>
> time for int[100] (ms): 0
> time for type[100] (ms): 0
>
> time for int[1000] (ms): 0
> time for type[1000] (ms): 0
>
> time for int[10000] (ms): 2
> time for type[10000] (ms): 2
>
> time for int[100000] (ms): 0
> time for type[100000] (ms): 11
>
> time for int[1000000] (ms): 0
> time for type[1000000] (ms): 2
>
> time for int[10000000] (ms): 0
> time for type[10000000] (ms): 18
>
> There is no doubt that enum is a bit slower than using static final int.
> But is it significant?
> Should we avoid using enum in our code in this case?
> Any comment?
>
> Thanks.
> Shing Wai Chan
>
> ------------------------------------------------------------------------
>
> import java.util.Random;
>
> public class EnumTest {
> public static enum Type {
> A,
> B,
> C,
> D,
> E,
> F,
> G,
> H,
> I,
> J
> }
>
> public static final int AA = 0;
> public static final int BB = 1;
> public static final int CC = 2;
> public static final int DD = 3;
> public static final int EE = 4;
> public static final int FF = 5;
> public static final int GG = 6;
> public static final int HH = 7;
> public static final int II = 8;
> public static final int JJ = 9;
>
> private static int[] genRandomInts(int count) {
> int[] is = new int[count];
> Random r = new Random();
> for (int i = 0; i < count; i++) {
> is[i] = r.nextInt(10);
> }
> return is;
> }
>
> private static Type[] genRandomTypes(int count) {
> Type[] ts = new Type[count];
> Random r = new Random();
> for (int i = 0; i < count; i++) {
> int temp = r.nextInt(10);
> if (temp == AA) {
> ts[i] = Type.A;
> } else if (temp == BB) {
> ts[i] = Type.B;
> } else if (temp == CC) {
> ts[i] = Type.C;
> } else if (temp == DD) {
> ts[i] = Type.D;
> } else if (temp == EE) {
> ts[i] = Type.E;
> } else if (temp == FF) {
> ts[i] = Type.F;
> } else if (temp == GG) {
> ts[i] = Type.G;
> } else if (temp == HH) {
> ts[i] = Type.H;
> } else if (temp == II) {
> ts[i] = Type.I;
> } else if (temp == JJ) {
> ts[i] = Type.J;
> }
> }
> return ts;
> }
>
> private static void testInt(int count) {
> int x = 0;
> int[] rs = genRandomInts(count);
>
> long t1 = System.currentTimeMillis();
> for (int r : rs) {
> if (r == AA) {
> x = 10;
> } else if (r == BB) {
> x = 11;
> } else if (r == CC) {
> x = 12;
> } else if (r == DD) {
> x = 13;
> } else if (r == EE) {
> x = 14;
> } else if (r == FF) {
> x = 15;
> } else if (r == GG) {
> x = 16;
> } else if (r == HH) {
> x = 17;
> } else if (r == II) {
> x = 18;
> } else if (r == JJ) {
> x = 19;
> } else {
> }
> }
> long t2 = System.currentTimeMillis();
> System.out.println("time for int[" + count + "] (ms): " + (t2 - t1));
> }
>
> private static void testEnum(int count) {
> int x = 0;
> Type[] ts = genRandomTypes(count);
>
> long t1 = System.currentTimeMillis();
> for (Type t : ts) {
> switch(t) {
> case A:
> x = 10;
> break;
> case B:
> x = 11;
> break;
> case C:
> x = 12;
> break;
> case D:
> x = 13;
> break;
> case E:
> x = 14;
> break;
> case F:
> x = 15;
> break;
> case G:
> x = 16;
> break;
> case H:
> x = 17;
> break;
> case I:
> x = 18;
> break;
> case J:
> x = 19;
> break;
> default:
> break;
> }
> }
> long t2 = System.currentTimeMillis();
> System.out.println("time for type[" + count + "] (ms): " + (t2 - t1));
> }
>
> public static void main(String args[]) {
> int[] cs = new int[] { 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
> for (int c : cs) {
> testInt(c);
> testEnum(c);
> }
> }
> }
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>

-- 
Charlie Hunt
Java Performance Engineer
<http://java.sun.com/docs/performance/>