Enum and code efficiency

B

Brian

I'd like to learn more about enums in 1.5. I'm a bit concerned about
the efficiency of an enum versus a final static variable. I have a
fairly tight inner loop that isn't running as fast as I'd like it
to and I suspect it's enums (lots of 'em) creating calls at runtime.

Here's a nonsensical example loosely based on dice. It's simple. My
guesses are included as to what is a compile time literal versus a
runtime call. Am I right?

Thanks.

public class Test {

public enum Axis {
RIGHT,
FRONT,
TOP,
BOTTOM,
BACK,
LEFT;
}

public enum Face {
ONE(Axis.RIGHT,"One"),
TWO(Axis.FRONT,"Two"),
THREE(Axis.TOP,"Three"),
FOUR(Axis.BOTTOM,"Four"),
FIVE(Axis.BACK,"Five"),
SIX(Axis.LEFT,"Six");

private Axis position;
private String label;

Face(Axis position, String label) {
this.label = label;
this.position = position;
}

public String getLabel() {
return label;
}

public Face opposite() {
switch (this) {
case ONE : return SIX;
case TWO : return FIVE;
case THREE : return FOUR;
case FOUR : return THREE;
case FIVE : return TWO;
case SIX : return ONE;
}
return null;
}
}

public static void main(String[] args) {
// Below are examples and my guess on when
// various "literals" are resolved

// Ex1. Definitely should be resolved at compile time
Axis myaxis = Axis.RIGHT;

// Ex2. Definitely should be resolved at compile time
Face mydie = Face.ONE;

// Ex3. Should be compile time
String mystring = mydie.getLabel();

// Ex4. Could be be compile time using a clever compiler
Face opposite = mydie.opposite();
}
}
 
A

Alan Moore

I'd like to learn more about enums in 1.5. I'm a bit concerned about
the efficiency of an enum versus a final static variable. I have a
fairly tight inner loop that isn't running as fast as I'd like it
to and I suspect it's enums (lots of 'em) creating calls at runtime.

Here's a nonsensical example loosely based on dice. It's simple. My
guesses are included as to what is a compile time literal versus a
runtime call. Am I right?

Thanks.

public class Test {

public enum Axis {
RIGHT,
FRONT,
TOP,
BOTTOM,
BACK,
LEFT;
}

public enum Face {
ONE(Axis.RIGHT,"One"),
TWO(Axis.FRONT,"Two"),
THREE(Axis.TOP,"Three"),
FOUR(Axis.BOTTOM,"Four"),
FIVE(Axis.BACK,"Five"),
SIX(Axis.LEFT,"Six");

private Axis position;
private String label;

Face(Axis position, String label) {
this.label = label;
this.position = position;
}

public String getLabel() {
return label;
}

public Face opposite() {
switch (this) {
case ONE : return SIX;
case TWO : return FIVE;
case THREE : return FOUR;
case FOUR : return THREE;
case FIVE : return TWO;
case SIX : return ONE;
}
return null;
}
}

public static void main(String[] args) {
// Below are examples and my guess on when
// various "literals" are resolved

// Ex1. Definitely should be resolved at compile time
Axis myaxis = Axis.RIGHT;

// Ex2. Definitely should be resolved at compile time
Face mydie = Face.ONE;

// Ex3. Should be compile time
String mystring = mydie.getLabel();

// Ex4. Could be be compile time using a clever compiler
Face opposite = mydie.opposite();
}
}

You can make this code more efficient the same way you would with
normal classes: make the "position" and "label" fields final; and
make the "opposite" method abstract, then provide the implementation
in the declaration of each constant.


public enum Face {
ONE(Axis.RIGHT,"One") {
public Face opposite() { return SIX; }
},
TWO(Axis.FRONT,"Two") {
public Face opposite() { return FIVE; }
},
THREE(Axis.TOP,"Three") {
public Face opposite() { return FOUR; }
},
FOUR(Axis.BOTTOM,"Four") {
public Face opposite() { return THREE; }
},
FIVE(Axis.BACK,"Five") {
public Face opposite() { return TWO; }
},
SIX(Axis.LEFT,"Six") {
public Face opposite() { return ONE; }
};

private final Axis position;
private fianl String label;

Face(Axis position, String label) {
this.label = label;
this.position = position;
}

public String getLabel() {
return label;
}

public abstract Face opposite();
}

This way, everything is known at compile-time, and can be inlined.
Enums are designed for efficiency, but their flexibility means you can
use them inefficiently. Try writing your enums like this and see if
they're still too slow. BTW, did you try using int/String constants
for comparison?
 
B

Brian

Alan Moore said:
I'd like to learn more about enums in 1.5. I'm a bit concerned about
the efficiency of an enum versus a final static variable. I have a
fairly tight inner loop that isn't running as fast as I'd like it
to and I suspect it's enums (lots of 'em) creating calls at runtime.

Here's a nonsensical example loosely based on dice. It's simple. My
guesses are included as to what is a compile time literal versus a
runtime call. Am I right?

Thanks.

public class Test {

public enum Axis {
RIGHT,
FRONT,
TOP,
BOTTOM,
BACK,
LEFT;
}

public enum Face {
ONE(Axis.RIGHT,"One"),
TWO(Axis.FRONT,"Two"),
THREE(Axis.TOP,"Three"),
FOUR(Axis.BOTTOM,"Four"),
FIVE(Axis.BACK,"Five"),
SIX(Axis.LEFT,"Six");

private Axis position;
private String label;

Face(Axis position, String label) {
this.label = label;
this.position = position;
}

public String getLabel() {
return label;
}

public Face opposite() {
switch (this) {
case ONE : return SIX;
case TWO : return FIVE;
case THREE : return FOUR;
case FOUR : return THREE;
case FIVE : return TWO;
case SIX : return ONE;
}
return null;
}
}

public static void main(String[] args) {
// Below are examples and my guess on when
// various "literals" are resolved

// Ex1. Definitely should be resolved at compile time
Axis myaxis = Axis.RIGHT;

// Ex2. Definitely should be resolved at compile time
Face mydie = Face.ONE;

// Ex3. Should be compile time
String mystring = mydie.getLabel();

// Ex4. Could be be compile time using a clever compiler
Face opposite = mydie.opposite();
}
}
You can make this code more efficient the same way you would with
normal classes: make the "position" and "label" fields final; and
make the "opposite" method abstract, then provide the implementation
in the declaration of each constant.

public enum Face {
ONE(Axis.RIGHT,"One") {
public Face opposite() { return SIX; }
},
TWO(Axis.FRONT,"Two") {
public Face opposite() { return FIVE; }
},
THREE(Axis.TOP,"Three") {
public Face opposite() { return FOUR; }
},
FOUR(Axis.BOTTOM,"Four") {
public Face opposite() { return THREE; }
},
FIVE(Axis.BACK,"Five") {
public Face opposite() { return TWO; }
},
SIX(Axis.LEFT,"Six") {
public Face opposite() { return ONE; }
};
private final Axis position;
private fianl String label;

Face(Axis position, String label) {
this.label = label;
this.position = position;
}

public String getLabel() {
return label;
}

public abstract Face opposite();
}
This way, everything is known at compile-time, and can be inlined.
Enums are designed for efficiency, but their flexibility means you can
use them inefficiently. Try writing your enums like this and see if
they're still too slow. BTW, did you try using int/String constants
for comparison?

Hi Alan -

I may have waited to late, but thanks for replying. It took me
a bit of time to get back to this. But your suggestions are
being worked into my code.

To answer your question, no, I didn't compare integer lables to
string labels. The strings are used infrequently, maily for
"developer output."

Thanks again.
 
A

Alan Moore

To answer your question, no, I didn't compare integer lables to
string labels. The strings are used infrequently, maily for
"developer output."

What I meant was, have you tried using old-style constants instead of
enums?
 
L

Lucy

Alan Moore said:
What I meant was, have you tried using old-style constants instead of
enums?

Also old style:

class AA {
public static void main(String[] args) {
int a = 5;
switch (a) {
case 'f'-'a' :
System.out.println("first");
break;
default :
System.out.println("default: " + a);
break;
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top