Reputation: 1225
I'm trying to understand compile versus run-time computation in java. I have the following enum
public enum SightSensor{
NORTH (new MapLocation[]{new MapLocation(0,1),
new MapLocation(0,2),
new MapLocation(0,3)}),
SOUTH (new MapLocation[]{new MapLocation(0,-1),
new MapLocation(0,-2),
new MapLocation(0,-3)});
private final MapLocation[] locs;
SightSensor(MapLocation[] locs){
this.locs = locs;
}
public static MapLocation[] getLocs(Direction dir){
if (dir == Direction.NORTH)
return NORTH.locs;
if (dir == Direction.SOUTH)
return SOUTH.locs;
}
};
In words, I want to define a constant mapping between a Direction and an array of MapLocations. (Perhaps this is the wrong way to do this? I'm new to Java.) Now, if I write
MapLocation[] locs = SightSensor.getLocs(Direction.SOUTH_WEST);
inside a loop in the code, I find that there is a cost overhead the first time the code is called, implying to me it is somehow being computed/instantiated at run time. If instead I just directly code
MapLocation[] locs = new MapLocation[]{new MapLocation(0,1),
new MapLocation(0,2),
new MapLocation(0,3)};
there is no cost overhead. I don't understand the difference. Does the compiler do some weird sort of just-in-time computation?
Upvotes: 0
Views: 194
Reputation: 8490
This is not really an answer, but a tip: Make getLocs
non-static and just return the locs
of the current enum:
public MapLocation[] getLocs(){
return locs;
}
Instead of SightSensor.getLocs(someDir)
you then call someDir.getLocs()
.
This way you avoid having to enumerate all members of the enum.
Upvotes: 0
Reputation: 30733
It seems that the cost you're seeing is the class-loading cost: the first time the code accesses a class, the class-loader loads its binary (.class file) into memory. This is a one time cost that for most practical purposes is negligible.
Moreover:
Now, if I write ... inside a loop in the code, I find that there is a cost overhead the first time the code is called,
How did you measure this cost? It is nearly impossible to measure the time cost of a single operation. You can measure the time needed to carry out xM passes thru a loop and then you can divide to get the amortized cost. However, measuring a single operation is difficult: you may be getting a Garbage Collection cycle, a thread-related context switch, etc. Moreover, the JIT (Just In Time) Compiler does not kick the first time a statement is executed, so measuring a single operation will usually give you a much higher cost than amortized cost over N operations.
FWIW, I would write getLocs()
as follows:
public static MapLocation[] getLocs(Direction dir) {
return valueOf(dir.name()).locs;
}
Alternatively, you can use replace the SightSensor enum with a variable of type EnumMap:
EnumMap<Direction, MapLocation[]> map = new EnumMap(Direction.class);
map.put(Direction.NORTH, new MapLocation[] { new MapLocation(0, 1),
new MapLocation(0, 2),
new MapLocation(0, 3) });
map.put(Direction.NORTH, new MapLocation[] { new MapLocation(0, -1),
new MapLocation(0, -2),
new MapLocation(0, -3) });
Then, getLocs()
calls simply become map.get(dir)
Upvotes: 3
Reputation: 308938
Does the compiler do some weird sort of just-in-time computation?
Yes, the Java run-time does use statistics to optimize the code as it runs:
http://docs.oracle.com/javase/6/docs/technotes/tools/share/jstat.html
Nothing weird about it.
This might be pertinent as well:
Real differences between "java -server" and "java -client"?
Personally, I think you should write the code to be as easy to read as possible and not worry about optimization. The speedup probably isn't significant.
Upvotes: 2