Home All Groups Group Topic Archive Search About

switch case and efficiency

Author
21 Dec 2008 8:35 PM
Martijn Mulder
I have well over a thousend cases after a switch.

1. Is there a practical limit to the number of cases?
2. Can I optimize (and uglify) my code so that switch-case runs faster?
3. How is switch implemented (binary search, linear search...)?

Thank you

Author
21 Dec 2008 9:49 PM
Family Tree Mike
" Martijn Mulder" <i@m> wrote in message
news:494ea8ac$0$24255$dbd49001@news.wanadoo.nl...
>I have well over a thousend cases after a switch.
>
> 1. Is there a practical limit to the number of cases?
> 2. Can I optimize (and uglify) my code so that switch-case runs faster?
> 3. How is switch implemented (binary search, linear search...)?
>
> Thank you
>


According to MSDN, there is no limit to the number of cases.   This is
stated on this page: http://msdn.microsoft.com/en-us/library/06tc147t.aspx.
Since the first case statement is matched, I think it is just a linear
search as the logic matches the first found case.

Not knowing what you are doing with each of the thousands of cases, it would
be hard to recommend what you should do to optimize things.  If you are
using a switch statement to find the house address of a list of phone
numbers, then obviously a better way can be recommended.

--
Mike
Are all your drivers up to date? click for free checkup

Author
21 Dec 2008 10:06 PM
Martijn Mulder
Show quote Hide quote
>>I have well over a thousend cases after a switch.
>>
>> 1. Is there a practical limit to the number of cases?
>> 2. Can I optimize (and uglify) my code so that switch-case runs faster?
>> 3. How is switch implemented (binary search, linear search...)?
>>
>> Thank you


> According to MSDN, there is no limit to the number of cases.   This is
> stated on this page:
> http://msdn.microsoft.com/en-us/library/06tc147t.aspx. Since the first
> case statement is matched, I think it is just a linear search as the logic
> matches the first found case.
>
> Not knowing what you are doing with each of the thousands of cases, it
> would be hard to recommend what you should do to optimize things.  If you
> are using a switch statement to find the house address of a list of phone
> numbers, then obviously a better way can be recommended.
>
> --
> Mike


In fact, the number is only a few hundreds, but rising. The great number
stems from a recent attempt to simplify key handling code with this
technique:

override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs a)
{
base.OnKeyDown(a);
switch(ModifierKeys.ToString()+' '+a.KeyCode)
{
case"Shift, Control F":
System.Console.WriteLine("You pressed the Shift, Control and F key
similtaniously" );
break;
}
}

It's neat, but it adds up
Author
21 Dec 2008 10:29 PM
Jeroen Mostert
Martijn Mulder wrote:
Show quoteHide quote
>>> I have well over a thousend cases after a switch.
>>>
>>> 1. Is there a practical limit to the number of cases?
>>> 2. Can I optimize (and uglify) my code so that switch-case runs faster?
>>> 3. How is switch implemented (binary search, linear search...)?
>>>
>
>> According to MSDN, there is no limit to the number of cases.   This is
>> stated on this page:
>> http://msdn.microsoft.com/en-us/library/06tc147t.aspx. Since the first
>> case statement is matched, I think it is just a linear search as the logic
>> matches the first found case.
>>
>> Not knowing what you are doing with each of the thousands of cases, it
>> would be hard to recommend what you should do to optimize things.  If you
>> are using a switch statement to find the house address of a list of phone
>> numbers, then obviously a better way can be recommended.
>>
>
> In fact, the number is only a few hundreds, but rising. The great number
> stems from a recent attempt to simplify key handling code with this
> technique:
>
> override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs a)
> {
> base.OnKeyDown(a);
> switch(ModifierKeys.ToString()+' '+a.KeyCode)
> {
> case"Shift, Control F":
> System.Console.WriteLine("You pressed the Shift, Control and F key
> similtaniously" );
> break;
> }
> }
>
Well, you might have mentioned that you were switching on strings, as it's
quite different from switching on integers.

The compiler will emit a lazily initialized hashtable containing all the
strings you're switching on, mapping them to integers. These, in turn, will
be used in a regular switch opcode.

Pretend you're building a hashtable yourself containing all the strings
you're switching on and you'll have a better idea of the limits. For
starters, if you have a great many cases, you'll be eating up a great deal
of memory. Switching is also none too efficient, as computing a hash over a
string is far less efficient than looking up a single number.

In any case, you probably don't need a switch statement at all, and I fail
to see how this "simplifies" key handling code, other than by saving you
conscious thought about what the cases have in common. The statement you
give as an example could be easily rewritten to a single series of print
statements. Even if your actual code is more complex, it's still very likely
that you could reduce it to a limited number of numerical switch statements
(for starters, every key plus modifiers easily fits in an int).

--
J.
Author
21 Dec 2008 10:56 PM
Martijn Mulder
Show quote Hide quote
"Jeroen Mostert" <jmost***@xs4all.nl> schreef in bericht
news:494ec364$0$188$e4fe514c@news.xs4all.nl...
>  Martijn Mulder wrote:
>>>> I have well over a thousend cases after a switch.
>>>>
>>>> 1. Is there a practical limit to the number of cases?
>>>> 2. Can I optimize (and uglify) my code so that switch-case runs faster?
>>>> 3. How is switch implemented (binary search, linear search...)?
>>>>
>>
>>> According to MSDN, there is no limit to the number of cases.   This is
>>> stated on this page:
>>> http://msdn.microsoft.com/en-us/library/06tc147t.aspx. Since the first
>>> case statement is matched, I think it is just a linear search as the
>>> logic matches the first found case.
>>>
>>> Not knowing what you are doing with each of the thousands of cases, it
>>> would be hard to recommend what you should do to optimize things.  If
>>> you are using a switch statement to find the house address of a list of
>>> phone numbers, then obviously a better way can be recommended.
>>>
>>
>> In fact, the number is only a few hundreds, but rising. The great number
>> stems from a recent attempt to simplify key handling code with this
>> technique:
>>
>> override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs a)
>> {
>> base.OnKeyDown(a);
>> switch(ModifierKeys.ToString()+' '+a.KeyCode)
>> {
>> case"Shift, Control F":
>> System.Console.WriteLine("You pressed the Shift, Control and F key
>> similtaniously" );
>> break;
>> }
>> }


> Well, you might have mentioned that you were switching on strings, as it's
> quite different from switching on integers.
>
> The compiler will emit a lazily initialized hashtable containing all the
> strings you're switching on, mapping them to integers. These, in turn,
> will be used in a regular switch opcode.
>
> Pretend you're building a hashtable yourself containing all the strings
> you're switching on and you'll have a better idea of the limits. For
> starters, if you have a great many cases, you'll be eating up a great deal
> of memory. Switching is also none too efficient, as computing a hash over
> a string is far less efficient than looking up a single number.
>
> In any case, you probably don't need a switch statement at all, and I fail
> to see how this "simplifies" key handling code, other than by saving you
> conscious thought about what the cases have in common. The statement you
> give as an example could be easily rewritten to a single series of print
> statements. Even if your actual code is more complex, it's still very
> likely that you could reduce it to a limited number of numerical switch
> statements (for starters, every key plus modifiers easily fits in an int).


IIUC the compiler will generate an efficient int-based switch that I cannot
beat, while I keep the readability, the flexibility and the extensibility on
my side? I am more than satisfied with that :)

Thank you
Author
21 Dec 2008 11:00 PM
Jeroen Mostert
Martijn Mulder wrote:
Show quoteHide quote
> "Jeroen Mostert" <jmost***@xs4all.nl> schreef in bericht
> news:494ec364$0$188$e4fe514c@news.xs4all.nl...
>>  Martijn Mulder wrote:
>>>>> I have well over a thousend cases after a switch.
>>>>>
>>>>> 1. Is there a practical limit to the number of cases?
>>>>> 2. Can I optimize (and uglify) my code so that switch-case runs faster?
>>>>> 3. How is switch implemented (binary search, linear search...)?
>>>>>
>>>> According to MSDN, there is no limit to the number of cases.   This is
>>>> stated on this page:
>>>> http://msdn.microsoft.com/en-us/library/06tc147t.aspx. Since the first
>>>> case statement is matched, I think it is just a linear search as the
>>>> logic matches the first found case.
>>>>
>>>> Not knowing what you are doing with each of the thousands of cases, it
>>>> would be hard to recommend what you should do to optimize things.  If
>>>> you are using a switch statement to find the house address of a list of
>>>> phone numbers, then obviously a better way can be recommended.
>>>>
>>> In fact, the number is only a few hundreds, but rising. The great number
>>> stems from a recent attempt to simplify key handling code with this
>>> technique:
>>>
>>> override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs a)
>>> {
>>> base.OnKeyDown(a);
>>> switch(ModifierKeys.ToString()+' '+a.KeyCode)
>>> {
>>> case"Shift, Control F":
>>> System.Console.WriteLine("You pressed the Shift, Control and F key
>>> similtaniously" );
>>> break;
>>> }
>>> }
>
>
>> Well, you might have mentioned that you were switching on strings, as it's
>> quite different from switching on integers.
>>
>> The compiler will emit a lazily initialized hashtable containing all the
>> strings you're switching on, mapping them to integers. These, in turn,
>> will be used in a regular switch opcode.
>>
>> Pretend you're building a hashtable yourself containing all the strings
>> you're switching on and you'll have a better idea of the limits. For
>> starters, if you have a great many cases, you'll be eating up a great deal
>> of memory. Switching is also none too efficient, as computing a hash over
>> a string is far less efficient than looking up a single number.
>>
>> In any case, you probably don't need a switch statement at all, and I fail
>> to see how this "simplifies" key handling code, other than by saving you
>> conscious thought about what the cases have in common. The statement you
>> give as an example could be easily rewritten to a single series of print
>> statements. Even if your actual code is more complex, it's still very
>> likely that you could reduce it to a limited number of numerical switch
>> statements (for starters, every key plus modifiers easily fits in an int).
>
>
> IIUC the compiler will generate an efficient int-based switch that I cannot
> beat, while I keep the readability, the flexibility and the extensibility on
> my side? I am more than satisfied with that :)
>
I have no idea how you derive this conclusion from my statements. Are you
saying you're *not* using strings?

If you're not actually interested in a full answer to the question, just in
hearing that what you're doing works and will probably not be too
inefficient: what you're doing works and will probably not be too
inefficient. Most optimizations aren't necessary.

--
J.
Author
21 Dec 2008 11:57 PM
Michael D. Ober
Show quote Hide quote
"Jeroen Mostert" <jmost***@xs4all.nl> wrote in message
news:494ec364$0$188$e4fe514c@news.xs4all.nl...
>  Martijn Mulder wrote:
>>>> I have well over a thousend cases after a switch.
>>>>
>>>> 1. Is there a practical limit to the number of cases?
>>>> 2. Can I optimize (and uglify) my code so that switch-case runs faster?
>>>> 3. How is switch implemented (binary search, linear search...)?
>>>>
>>
>>> According to MSDN, there is no limit to the number of cases.   This is
>>> stated on this page:
>>> http://msdn.microsoft.com/en-us/library/06tc147t.aspx. Since the first
>>> case statement is matched, I think it is just a linear search as the
>>> logic matches the first found case.
>>>
>>> Not knowing what you are doing with each of the thousands of cases, it
>>> would be hard to recommend what you should do to optimize things.  If
>>> you are using a switch statement to find the house address of a list of
>>> phone numbers, then obviously a better way can be recommended.
>>>
>>
>> In fact, the number is only a few hundreds, but rising. The great number
>> stems from a recent attempt to simplify key handling code with this
>> technique:
>>
>> override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs a)
>> {
>> base.OnKeyDown(a);
>> switch(ModifierKeys.ToString()+' '+a.KeyCode)
>> {
>> case"Shift, Control F":
>> System.Console.WriteLine("You pressed the Shift, Control and F key
>> similtaniously" );
>> break;
>> }
>> }
>>
> Well, you might have mentioned that you were switching on strings, as it's
> quite different from switching on integers.
>
> The compiler will emit a lazily initialized hashtable containing all the
> strings you're switching on, mapping them to integers. These, in turn,
> will be used in a regular switch opcode.
>
> Pretend you're building a hashtable yourself containing all the strings
> you're switching on and you'll have a better idea of the limits. For
> starters, if you have a great many cases, you'll be eating up a great deal
> of memory. Switching is also none too efficient, as computing a hash over
> a string is far less efficient than looking up a single number.
>
> In any case, you probably don't need a switch statement at all, and I fail
> to see how this "simplifies" key handling code, other than by saving you
> conscious thought about what the cases have in common. The statement you
> give as an example could be easily rewritten to a single series of print
> statements. Even if your actual code is more complex, it's still very
> likely that you could reduce it to a limited number of numerical switch
> statements (for starters, every key plus modifiers easily fits in an int).
>
> --
> J.
>


You can make this easier to maintain by doing a two layer switch.  The first
layer will be on the function keys and is only 8 switches long similar to
the following.

Switch ModiferKeys
case Shift : ProcessShift(a)
case Ctrl : ProcessCtrl(a)
case Alt : ProcessAlt(a)
case Shift+Ctrl : ProcessShiftCtrl(a)
case Shift+Alt : ProcessShiftAlt(a)
case Shift+Ctrl+Alt : ProcessShiftCtrlAlt(a)
case Ctrl+Alt : ProcessCtrlAlt(a)
case else : ProcessRaw(a)
end Switch

Each of the Process<Shiftkeys>(a) would then be used to process the actual
keys for that combination of Ctrl, Shift, and Alt.  This will simplify your
code maintenance.  The reality is that the computer is far faster than your
users, so the small extra time required to call the second function will
never be noticed.

Mike Ober.
Author
21 Dec 2008 10:05 PM
Jeroen Mostert
Martijn Mulder wrote:
> I have well over a thousend cases after a switch.
>
Then you may have a design issue, and a possible maintenance issue. I do
hope that file is machine generated. Even so, see if there's a more compact
way. Are all the case statements unique, with no opportunity for generalization?

> 1. Is there a practical limit to the number of cases?

I honestly don't know. When your compiler times out, eats up too much memory
or crashes with an internal error, you've probably hit it. This is the most
likely case. It would also be possible for the CLR to hit the limit as it's
loading or JIT-compiling your code, but this seems less likely.

There are no relevant theoretical upper limits. If we assume that the switch
is always implemented with a jump table (i.e. there is no opportunity for
optimizing it further by rewriting the case blocks) then it can't have more
than 4 294 967 295 cases, but this will hardly be the limiting factor in any
case (for starters, the table alone would take up 16 GiB). And even then
there's no rule that it has to be implemented like this.

This is one of those "if you have to ask, it's probably time to rethink your
solution" kind of limits.

> 2. Can I optimize (and uglify) my code so that switch-case runs faster?

There is no *general* way to optimize a switch, it's already the purest
expression of "if this, then that". Depending on the specifics (what you're
doing in every case block, what values you're using for both switch and
cases and what the compiler/runtime are doing) it may be possible to
optimize it. For example, you could replace it with something else
altogether, like a hashtable and a general function.

> 3. How is switch implemented (binary search, linear search...)?
>
It depends on the compiler, the CLR and the specific statement.

The compiler may choose to emit a series of compares and jumps (likely if
the switches are wildly disparate), or it may emit a switch opcode (if the
switches are consecutive) or a combination of these. That's just what
Microsoft's current C# compiler does, mind you -- certainly nothing
prohibits the compiler from, say, generating a minimal perfect hash function
and using that to index a jump table. (Which, incidentally, is another
possible way of optimizing your switch by replacing it with something else.)

These opcodes may in turn be compiled by the CLR in whatever way it chooses.
I'm not aware of any guarantee on the efficiency of the switch statement,
and the CIL specification certainly doesn't mandate one. The switch opcode
(which requires consecutive, zero-based values) is almost certainly
implemented as an indexed jump, as there's no general way to do it better.
The CLR may or may not recognize a series of compares-and-jumps as a
high-level switch statement and optimize accordingly.

In short: if you're that interested in efficiency, profile.

--
J.
Author
22 Dec 2008 2:22 AM
Arne_Vajhøj
Jeroen Mostert wrote:
>  Martijn Mulder wrote:
>> I have well over a thousend cases after a switch.
>>
> Then you may have a design issue, and a possible maintenance issue. I do
> hope that file is machine generated. Even so, see if there's a more
> compact way. Are all the case statements unique, with no opportunity for
> generalization?

Just as some define procedural programming as goto free
programming, then other define object oriented programming
as switch free programming.

There are also plenty of coding conventions that
limit method length to 50 or 100 lines.

I don't agree with those rules being the ultimate truth.
But non the less a method violating several common
coding rules is a good indication that something
is wrong.

Conclusion: I had to use 9 lines to say that I agree
with Jeroen.

Arne

Bookmark and Share