83

I've tried to google this, but had no luck.

I have a very big switch, and some cases are obviously more common than others.

So I would like to know if the order is really held as it is and the "upper" cases get tested before the "lower", therefore being evaluated faster.

I'd like to keep my order, but if it hurts speed, then reordering the branches would be a good idea.

For illustration:

switch (mark) {
        case Ion.NULL:
            return null;

        case Ion.BOOLEAN:
            return readBoolean();

        case Ion.BYTE:
            return readByte();

        case Ion.CHAR:
            return readChar();

        case Ion.SHORT:
            return readShort();

        case Ion.INT:
            return readInt();

        case Ion.LONG:
            return readLong();

        case Ion.FLOAT:
            return readFloat();

        case Ion.DOUBLE:
            return readDouble();

        case Ion.STRING:
            return readString();

        case Ion.BOOLEAN_ARRAY:
            return readBooleans();

        case Ion.BYTE_ARRAY:
            return readBytes();

        case Ion.CHAR_ARRAY:
            return readChars();

        case Ion.SHORT_ARRAY:
            return readShorts();

        case Ion.INT_ARRAY:
            return readInts();

        case Ion.LONG_ARRAY:
            return readLongs();

        case Ion.FLOAT_ARRAY:
            return readFloats();

        case Ion.DOUBLE_ARRAY:
            return readDoubles();

        case Ion.STRING_ARRAY:
            return readStrings();

        default:
            throw new CorruptedDataException("Invalid mark: " + mark);
    }
MightyPork
  • 18,270
  • 10
  • 79
  • 133
  • 24
    It isn't a bottleneck, and I have profiled it actually. I just want to know if this really affects execution speed - out of curiosity, pretty much. – MightyPork Apr 21 '14 at 19:39
  • 1
    I'm pretty sure the order makes no difference at all. The JVM doesn't go through the cases in order like a big long else/if. It's more of a "look up where to go next" kind of thing. – Dawood ibn Kareem Apr 21 '14 at 19:40
  • 2
    Yeah, but it must go through some sort of lookup table in order to do this, right? – MightyPork Apr 21 '14 at 19:41
  • Yes, but it can reorder that lookup table. – Louis Wasserman Apr 21 '14 at 19:41
  • You mean, reorder in runtime? Like, it thinks "hm.., byte arrays are pretty hot topic, let's put it at the top"? – MightyPork Apr 21 '14 at 19:42
  • 1
    First of all the difference in speed will be minimal no matter what approach the compiler uses unless you have thousands of cases. Second, _what is the declared type of `mark`_? If it's an enum then a jump table will be used; if it's an int then it'll use a jump table or a series of if-then-elses depending on the "density" of the values. – Jim Garrison Apr 21 '14 at 19:51
  • It's an int, as I need to have support for custom marks elsewhere in the code. – MightyPork Apr 21 '14 at 19:53
  • 2
    In this example using object orientation and polymorphism might be a better approach. E.g `IonBase` defines and abstract method `read()`; FloatIon, BooleanIon, BooleanArrayIon, etc. override `read()`. And instead of the `switch` do `return mark.read()`. – Kasper van den Berg Apr 22 '14 at 11:10
  • 1
    @KaspervandenBerg nothing against you worshiping polymorphism, but I'm working with a binary stream and Ion.SOMETHING are byte marks representing objects to read. Doing it the way you suggest would maybe look good in principle, but would add a lot of useless overhead. – MightyPork Apr 22 '14 at 18:56
  • See also http://stackoverflow.com/questions/22110707/how-is-string-in-switch-statement-more-efficient-than-corresponding-if-else-stat – Raedwald Apr 26 '14 at 08:42

1 Answers1

116

Reordering a switch statement does not have any effect.

Looking at the Java bytecode spec, a switch can either be compiled to a lookupswitch or a tableswitch instruction, switching on an int. A lookupswitch is always compiled with the possible values in sorted order, so reordering the constants in the code will never matter, and a tableswitch just has an array of the possible jumps relative to a specified offset, so it, too, never cares about the original order.

See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.lookupswitch and http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.tableswitch for details.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Wow, honestly I didn't even know bytecode has specs :D / Ok, so I won't mess up my switch to get imaginary speed gain. – MightyPork Apr 21 '14 at 19:56
  • 14
    I suppose the next follow-up question is: does the sorted order of values matter? (if Ion.NULL is more common than Ion.BOOLEAN, will it be faster if Ion.NULL < Ion.BOOLEAN?) – user253751 Apr 22 '14 at 08:39
  • See also http://stackoverflow.com/questions/12020048/how-does-javas-switch-work-under-the-hood – Raedwald Apr 26 '14 at 08:50