J
Joshua Cranmer
I decompiled a number of switches a while back, and was disappointed
to see it nearly always use lookupswitch, even where I would have used
tableswitch. This suggests, if you want to guarantee the efficient
version, design your keys to be dense ints starting at 0. You can
often replace a switch with an array or Map data lookup, or array
lookup of a delegate.
From OpenJDK:
long table_space_cost = 4 + ((long) hi - lo + 1); // words
long table_time_cost = 3; // comparisons
long lookup_space_cost = 3 + 2 * (long) nlabels;
long lookup_time_cost = nlabels;
int opcode =
nlabels > 0 &&
table_space_cost + 3 * table_time_cost <=
lookup_space_cost + 3 * lookup_time_cost
?
tableswitch : lookupswitch;
In other words, it must be that about 1/5 of the range is filled with
labels to use a table switch (rather, 1/5 of the range + 11). This
meshes well with what I know from playing around with a custom-built
bytecode reader, namely that it took surprisingly few case statements in
a large table (Java's bytecode consumes around 200 different values),
namely that it switched to tableswitch by the time I enabled the if*
opcodes.