Order of Enum in Case Statement
A while back my manager asked me if the order of the enums in a Delphi case statement changed performance: i.e. Enums in order being faster then those not. I was pretty sure it didn’t, but thought it was worth checking out. Time for a test application and some disassembly . . .
Here are my types and variables, which are the same for both examples.
type
TMyEnum = (my1, my2, my3, my4);
var
myEnum: TMyEnum;
val: Char;
Here are the two examples, side by side, with assembly code to follow. BTW, compiler optimization was turned on.
| Case enum in order | Case enum out of order | ||
|---|---|---|---|
|
|
||
| —– Disassembly —– | |||
| case myEnum of | case myEnum of | ||
| BF9E | sub al,$01 | C00A | sub al,$01 |
| BFA0 | jb $bfae | C00C | jb $c01e |
| BFA2 | jz $bfb2 | C00E | jz $c026 |
| BFA4 | dec al | C010 | dec al |
| BFA6 | jz $bfb6 | C012 | jz $c01a |
| BFA8 | dec al | C014 | dec al |
| BFAA | jz $bfba | C016 | jz $c022 |
| BFAC | jmp $bfbe | C018 | jmp $c02a |
| my1: val := ‘1′; | my3: val := ‘3′; | ||
| BFAE | mov bl,$31 | C01A | mov bl,$33 |
| BFB0 | jmp $bfc0 | C01C | jmp $c02c |
| my2: val := ‘2′; | my1: val := ‘1′; | ||
| BFB2 | mov bl,$32 | C01E | mov bl,$31 |
| BFB4 | jmp $bfc0 | C020 | jmp $c02c |
| my3: val := ‘3′; | my4: val := ‘4′; | ||
| BFB6 | mov bl,$33 | C022 | mov bl,$34 |
| BFB8 | jmp $bfc0 | C024 | jmp $c02c |
| my4: val := ‘4′; | my2: val := ‘2′; | ||
| BFBA | mov bl,$34 | C026 | mov bl,$32 |
| BFBC | jmp $bfc0 | C028 | jmp $c02c |
| val := ‘?’; | val := ‘?’; | ||
| BFBE | mov bl,$20 | C02A | mov bl,$20 |
Same number of lines of assembly code. There may be some internal CPU optimization, but I don’t expect there is any.
Conclusion: Order of the enum in the case statement does not change performance. Anyone else have any details I missed, or evidence to the contrary? I guess the next step is to test it in .NET and IL. . . .
Tags: Assembly, disassembly, Enumerations, performance, Win32
July 13th, 2008 at 1:26 am
I think the issue is if the order matters with respect to the most probable cases. That is to say if your enum has options a-b-c and 90% of the time it is option a, then you should put the code for option a first.
July 13th, 2008 at 10:33 am
A while ago I did a similar test and wrote down my results here:
http://www.delphipraxis.net/topic41187_delphiinternals+compilerverhalten+bei+case+statements.html&highlight=
You should be able to read German, though
Regards
Daniel
July 14th, 2008 at 3:28 am
Although the compiler always optimizes a case loop to be in-order,
Olivier is right: You also need to watch your algoritm.
That also implies that when you know some code is more likely to occur than other code in the case loop, you need to enforce it by evaluating from a low (the lowest) const value.
But that assumes the compiler will optimize from low to high, and that may not be the case: the compiler may also optimize high to low….
Some compilers do…
All in all, Olivier: it is pretty dangerous to rely on perceived optimizations that you can not be sure about and maybe version dependent.
In your case: you can better write out your algoritm in such a way that the optimization you want is enforced, i.e. f.e. by evaluating the most commonly encountered code first by means of if/then…/else /case/endcase