473,395 Members | 1,968 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Hundreds of cases in a switch, optimization?

Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?

In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses? Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?

Thanks,
--
He Shiming
Nov 14 '05 #1
65 6590
there should be no difference between if-elsses and switches in terms
of performance. switches are only easier to read. ie, they produce
identical machine code.
by the way, i am talking from a pascal point of view but it should
also apply to C . Waiting like you for C guys to answer.

Nov 14 '05 #2
Well, thanks for the information anyway.

--
He Shiming

"Alawna" <O.******@gmail.com> wrote in message
news:11*********************@g49g2000cwa.googlegro ups.com...
there should be no difference between if-elsses and switches in terms
of performance. switches are only easier to read. ie, they produce
identical machine code.
by the way, i am talking from a pascal point of view but it should
also apply to C . Waiting like you for C guys to answer.

Nov 14 '05 #3


He Shiming (NOSPAM) wrote:
Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?

In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses? Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?


Well, try to write these hundreds of switch statements using if-else's
and see if you have it easy that way.

I have seen a lot of code with 100's of switch statements in many cases
it is just not _possible_ to apply any other strategy. However, as far
as performance is concerned try to keep the cases that you feel are
most likely to occur at the beginning of the switch block.
--
Imanpreet Singh Arora

Nov 14 '05 #4
In article <d9**********@news.yaako.com>,
"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote:
Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?
How could I know? Does it run fast enough? Does anyone complain that it
is too slow? Have you measured how long it takes?

In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses? Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?


It is time to read the documentation for your compiler and find out how
to show the assembler code that it produces. Find out, then have a look
at the code.

Since compilers are around over fourty years, there are the following
possibilities:

a. There is no way to do a switch statement of 200 cases faster than
200 if's.
b. It is possible to do a switch statement of 200 cases faster than
200 if's, but compiler writers for the last 40 years have been too
stupid or too lazy to implement it.
c. It's done much faster, and has been done that way for years.

Guess a, b or c.
Nov 14 '05 #5
In article <11*********************@g49g2000cwa.googlegroups. com>,
Alawna <O.******@gmail.com> wrote:
:there should be no difference between if-elsses and switches in terms
:of performance. switches are only easier to read. ie, they produce
:identical machine code.
:by the way, i am talking from a pascal point of view but it should
:also apply to C . Waiting like you for C guys to answer.

When you look at it from a pascal point of view... you are incorrect,
at least in some implementations. I used to work with a Pascal
compiler which would do "finite-difference" methods on the switch
values in order to detect "runs" of labels, and would convert
those runs into table indices. Labels were internally
re-ordered at need.

Whether or not "runs" are used, when the case values are
constants and there are no "fall through" locations
(i.e., each case ends with a 'break' instead of continuing
on to the next label becasue no 'break' was specified),
then the compiler can sort the labels and drop in a binary
search over the values -- finding the right section of
code in log2(N) comparisions instead of N-1 comparisions.
--
Feep if you love VT-52's.
Nov 14 '05 #6
He Shiming (NOSPAM) wrote:
Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?


to my understandin, switch-cases n if-thens evaluate each expr until a
match is found (if no match is found then 'default' or the last else is
used). one way 2 optimize such irrelevant checkin wud b 2 use an arrays
of funtion ptrs. but of course, ur switch-case expr shud b sumthin like
case 1,case 2..., or it shud b possible to hash the cases to such a
range of numbers.

cheers.

Nov 14 '05 #7
Well, I'll have to do a performance profile (which is kinda complicated) if
I were to find out about what cases are being accessed most frequently. I
can't tell because there are hundreds of them.

So, is it true that to get to the last "case" of a switch block, the
processor needs to iterate through the whole list every time? If so, I could
split 200 cases into like 5 unit and do a value-comparision before entering
the switch. But is it worth it to do so? (especially when there are 200
cases).

--
He Shiming

"Minti" <im*******@gmail.com> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...


Well, try to write these hundreds of switch statements using if-else's
and see if you have it easy that way.

I have seen a lot of code with 100's of switch statements in many cases
it is just not _possible_ to apply any other strategy. However, as far
as performance is concerned try to keep the cases that you feel are
most likely to occur at the beginning of the switch block.
--
Imanpreet Singh Arora

Nov 14 '05 #8
Switches cases most often use jump tables and evaluate where as the if
else do not use them. Thus switches may give an illusion of being fast
but its not necessary,the only thing is that compilation may be a bit
fast not the execution. It asically depends on how intelligent the
compiler is. If its a good compiler they may be converted to the same
amount of c code or c++ code what ever.

And if you want ptimiztion then dont rely only on C++ compiler you can
do some on your own by grouping something or even re ordering the
structures.

Nov 14 '05 #9
He Shiming wrote:
I have seen a lot of code with 100's of switch statements
in many cases
it is just not _possible_ to apply any other strategy.


If the cases are all consecutive integers,
then you could rewrite it as functions
with an array of function pointers
to just index the correct function in one shot.

--
pete
Nov 14 '05 #10

Le 19/06/2005 11:08, dans
11*********************@f14g2000cwb.googlegroups.c om, «*forayer*»
<th********@hotmail.com> a écrit*:
to my understandin, switch-cases n if-thens evaluate each expr until a
match is found (if no match is found then 'default' or the last else is
used). one way 2 optimize such irrelevant checkin wud b 2 use an arrays
of funtion ptrs. but of course, ur switch-case expr shud b sumthin like
case 1,case 2..., or it shud b possible to hash the cases to such a
range of numbers.

cheers.


<OT>
Please avoid "b" "n" "2" "ur" and such things.
They make reading rather inconvenient (at least for a french reader) ;-)
</OT>

Nov 14 '05 #11


Jean-Claude Arbaut wrote:
<OT>
Please avoid "b" "n" "2" "ur" and such things.
They make reading rather inconvenient (at least for a french reader) ;-)
</OT>


i'll keep that in mind from now on, and i do apologize for any
inconvenience caused to anyone. sorry.

cheers,
forayer

Nov 14 '05 #12

Le 19/06/2005 13:07, dans
11**********************@g43g2000cwa.googlegroups. com, «*forayer*»
<th********@hotmail.com> a écrit*:


Jean-Claude Arbaut wrote:
<OT>
Please avoid "b" "n" "2" "ur" and such things.
They make reading rather inconvenient (at least for a french reader) ;-)
</OT>


i'll keep that in mind from now on, and i do apologize for any
inconvenience caused to anyone. sorry.


Well, I do apologize for my own english mistakes ;-)

Nov 14 '05 #13
In article <11**********************@g49g2000cwa.googlegroups .com>,
"Minti" <im*******@gmail.com> wrote:
He Shiming (NOSPAM) wrote:
Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?

In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses? Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?


Well, try to write these hundreds of switch statements using if-else's
and see if you have it easy that way.

I have seen a lot of code with 100's of switch statements in many cases
it is just not _possible_ to apply any other strategy. However, as far
as performance is concerned try to keep the cases that you feel are
most likely to occur at the beginning of the switch block.

If you are concerned about execution speed, then
Look at the assembler code.
Measure the execution time.
Learn what makes it fast

But only if
Making it faster would actually help somebody.

In my experience, the biggest performance gains can be achieved by
finding the bits in your code that are not just slow but completely
braindamaged slow, and fixing them. Not the kind where you ask "what is
faster: Switch or If", but the kind where you ask yourself "how could
anyone be so stupid to write code that way? "

Learn to find these bits of code and learn to use tools to find them.
Nov 14 '05 #14
On Sun, 19 Jun 2005 13:32:14 +0800, He Shiming wrote:
Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?
If it runs too slowly then you should probably look to optimise it in some
way.
In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses?
However the compiler chooses. Most reasonable compilers will attempt to
optimise switch statement using jump tables or range division (or a
combination) where appropriate. How efeectively that can be done depends
in the case values you are using.

It is also possible for a compiler to optimise a chain of if else
statements (e.g. one that tests a variable against various values) in a
similar way so you can't assume that that would be less efficient.
Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?


It is reasonable to assume that compilers will deal with switch statements
sensibly, and only worry about it, e.g. by looking at the assembly it
produces, if you suspect a compiler isn't doing what you want.

Lawrence

Nov 14 '05 #15
Alawna wrote:

there should be no difference between if-elsses and switches in
terms of performance. switches are only easier to read. ie, they
produce identical machine code.


Not necessarily so. An if else has to test everything in turn. A
switch (or CASE in Pascal) can (but may not) use a transfer table,
in which case there is no additional overhead to adding cases.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)

Nov 14 '05 #16
Oh that's definitely a great idea, I'll try, thanks.

--
He Shiming

"pete" <pf*****@mindspring.com> wrote in message
news:42***********@mindspring.com...
He Shiming wrote:

If the cases are all consecutive integers,
then you could rewrite it as functions
with an array of function pointers
to just index the correct function in one shot.

--
pete

Nov 14 '05 #17
Alrighty, I got the picture, thanks.

--
He Shiming

"DeltaOne" <sh**********@wipro.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Switches cases most often use jump tables and evaluate where as the if
else do not use them. Thus switches may give an illusion of being fast
but its not necessary,the only thing is that compilation may be a bit
fast not the execution. It asically depends on how intelligent the
compiler is. If its a good compiler they may be converted to the same
amount of c code or c++ code what ever.

And if you want ptimiztion then dont rely only on C++ compiler you can
do some on your own by grouping something or even re ordering the
structures.

Nov 14 '05 #18
In article <d9**********@news.yaako.com>,
"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote:
Well, I'll have to do a performance profile (which is kinda complicated) if
I were to find out about what cases are being accessed most frequently. I
can't tell because there are hundreds of them.

So, is it true that to get to the last "case" of a switch block, the
processor needs to iterate through the whole list every time? If so, I could
split 200 cases into like 5 unit and do a value-comparision before entering
the switch. But is it worth it to do so? (especially when there are 200
cases).


One more time: Look at the assembler code if it matters.
(And in most compilers that you will ever see it doesn't make the
slightest difference how you arrange your labels. In some especially
clever Java implementation, it may happen that the most common case
executes fastest - no matter where you put it. )
Nov 14 '05 #19
In article <11*********************@f14g2000cwb.googlegroups. com>,
"forayer" <th********@hotmail.com> wrote:
He Shiming (NOSPAM) wrote:
Hi,

I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?


to my understandin, switch-cases n if-thens evaluate each expr until a
match is found (if no match is found then 'default' or the last else is
used). one way 2 optimize such irrelevant checkin wud b 2 use an arrays
of funtion ptrs. but of course, ur switch-case expr shud b sumthin like
case 1,case 2..., or it shud b possible to hash the cases to such a
range of numbers.


Did you verify your understanding by measuring the actual speed or
looking at code that was generated? I don't think so.
Nov 14 '05 #20
In article <d9**********@news.yaako.com>,
"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote:
Oh that's definitely a great idea, I'll try, thanks.


Please. PLEASE. Think about it for a second.

Compilers have been doing this kind of stuff for decades.

If there were any simple method that you could use to replace your
switch statement and make it faster, then your compiler would use it.

Of course, you are always free to spend a few hours writing functions,
setting up an array of function pointers, and so on and so on and the
next guy who will have to maintain your code will be cursing you. Might
be you, anyway.
Nov 14 '05 #21
In article <d9**********@news.yaako.com>,
He Shiming <mailbill(NOSPAM)@21cn.com.nospam> wrote:
I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?


Only you can tell us that! Try it and see if it's fast enough.

Obviously your results will depend on the compiler. When I last
looked at this (about 15 years ago), most compilers would generate a
jump table if the values were consecutive or mostly consecutive, and
perhaps generate several jump tables if there were several ranges of
consecutive values. So try to use consecutive values.

If you need to squeeze every last ounce of speed out of it (if, say,
you are implementing some other language with a virtual machine) there
are a number of things that you might do.

- Put in dummy cases to make the values consecutive.

- Bear in mind that switch is defined to do nothing if none of the
cases match, so even with a consecutive range it has to test against
the maximum and minimum. I once hoped that the use of enum
values would help here, but it doesn't because you can assign
"incorrect" values to an enum. Using an unsigned type starting
at zero will let you avoid the minimum test. If you use all
256 values of an 8-bit type there will be no need to check at all.

- If your portability requirements don't prevent it, you could use
an extension such as gcc's which allows you to assign labels to
variables, so instead of using a switch you can use a goto. You
can also (portably) use a table of function pointers but the overhead
of a function call (including loss of local variables) may be worse
than the switch overhead.

- If all else fails, modify the generated assembly code.

And of course, you should only consider any of this if you really need
to!

-- Richard
Nov 14 '05 #22
Jean-Claude Arbaut wrote:
<th********@hotmail.com> a écrit :

.... snip ...
one way 2 optimize such irrelevant checkin wud b 2 use an arrays
of funtion ptrs. but of course, ur switch-case expr shud b sumthin
like case 1,case 2..., or it shud b possible to hash the cases to
such a range of numbers.


<OT>
Please avoid "b" "n" "2" "ur" and such things.
They make reading rather inconvenient (at least for a french reader)
;-) </OT>


Or to an English reader. Their prime effects are to make the
writer appear childish, and to lessen the probability of anyone
reading his or her output.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
Nov 14 '05 #23

"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote
I just wrote a function that has over 200 "cases" wrapped in a "switch"
statement. I'm wondering if there are performance issues in such
implementation. Do I need to optimize it some way?
Does the program run too slowly? Normally we are not too interested in how
fast a program executes until it takes more than about a tenth of a second
to respond, which is perceived by the users as instantaneous. If it takes a
second to respond, it may or may not be worth shaving off a tenth of a
second. If it takes ten minutes to respond, it probably is worth while
reducing that time to nine minutes.
In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses? Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?

Most compilers will try to generate a jump table for a large switch, which
is likely to be faster than an if .. else ladder. However sometimes you can
optimise. let's say you have a databse of millions of customers and are
doing a switch on the code for a title. Approximately half your customers
will be "Mr", about a third will probably be "Mrs", a lesser number "Miss"
and some "Ms" (depending on the characteristics of your customer base). You
will also have a sprinking of "Dr"s, "Sir"s, and if you are lucky a customer
you very much want to keep with the title "Queen".

Now if we arrange the if .. else ladder with "Mr" as the first condition,
"Mrs" as the second, and "Queen" as the last condition, then about half the
time if will evaluate only a single condition. Only once will it go all the
way down the ladder when it finds the title for the Elizabeth Windsor.

This could easily be faster than a switch, but may not be.

Generally you will only get a few percentage points improvement by this type
of micro-optimisation. This may be worth having, but it is usually the last
thing you should try.
Nov 14 '05 #24


Christian Bau wrote:
Did you verify your understanding by measuring the actual speed or
looking at code that was generated? I don't think so.


step-by-step execution in a debugger works for me! and yes, the
switch-cases did jump.

forayer.

Nov 14 '05 #25
On Sun, 19 Jun 2005 13:32:14 +0800, He Shiming wrote:
In terms of generated machine code, how does hundreds of cases in a switch
differ from hundreds of if-elses? Do compilers or processors do any
optimization on such structured code? Do I need to worry about the
performance, usually?


I got curious about this so I decided to see what one compiler did on one
architecture. I chose the simplest kind of test that would be the most
likely to optimised -- consecutive integers from 0 to N. I wrote a script
that made programs of this form:

#include <stdlib.h>

extern int f(int x, int nc);

void use_if_stmt(int n)
{
int x = 0;
while (n--) {
int v = f(n, <nc>);
if (v == 0) x++;
else if (v == 1) x++;
}
}

void use_switch_stmt(int n)
{
int x = 0;
while (n--) {
int v = f(n, <nc>);
switch (v) {
case 0: x++; break;
case 1: x++; break;
}
}
}

int main(int argc, char **argv)
{
int n = argc > 1 ? strtol(argv[1], NULL, 0) : 10000000;
use_if_stmt(n);
use_switch_stmt(n);
return 0;
}

where the number of cases (and "if" choices) could be varied (<nc> gets
replaced by this value as well). The function f could be one of "low",
"spread", or "high" and the resulting code was linked with the following:

int spread(int n, int nc) { return n % nc; }
int low (int n, int nc) { return 0; }
int high (int n, int nc) { return n + nc; }

to simulate the situation where the value to be matched was always the
first ("low"); evenly spread over the range of choices ("spread"); or
higher than the highest case ("high"). The resulting programs where
compiled both with (gcc -O2) and without optimisation. gprof was used to
compare the running times of the two functions "use_if_stmt" and
"use_switch_stmt". I simply calculated the ration of the "if" time
to the "switch" time, so a result of 1 means that they both took
the same time. A value of 5 means the if version took five times
as long as the switch version.

Without optimisation the results were:

N cases all low spread all high
2 0.8 1.1 0.8
20 0.8 1.7 5.5
200 0.9 8.1 66.4
2000 0.9 112.6 3042.0

almost exactly as I would have guessed. When the value being matched is
the first case, "if" is always faster. With 200 cases and all of the
value off the top of the case range, "if" takes 66 times longer.

What surprised me was the optimised numbers:

N cases all low spread all high
2 1.1 0.9 1.0
20 1.3 0.7 0.9
200 1.2 0.9 1.1
2000 0.8 1.1 1.0

I think that is quite impressive!

gcc (GCC) 3.4.3 on Pentium(R) M processor 1.70GHz

--
Ben.

Nov 14 '05 #26
> I just wrote a function that has over 200 "cases" wrapped in a
"switch" statement. I'm wondering if there are performance issues in
such implementation. Do I need to optimize it some way?

In terms of generated machine code, how does hundreds of cases in a
switch differ from hundreds of if-elses? Do compilers or processors
do any optimization on such structured code? Do I need to worry about
the performance, usually?


If you know something about the range of values you are testing, you can a
binary search-like approach. Of course this system will not be beaten by a
jump table, and with nowadays pipes, caches and what-not, the misses by the
CPU might even make it less efficient, I haven't tested any of it. But what
I am implying, is something like this:

if ( n < SOMEVALUE )
{
switch ( n )
{
// cases go here
}
}
else
{
switch ( n )
{
// remaining cases go here
}
}

You can introduce multiple levels as desired. Of course this may or may not
be faster for your compiler. And it (may) hurt(s) readability a little bit
also.

And as always with optimizing: make sure it _needs_ to be optimized. If the
particular code is only executed rarely and performance is not an issue
otherwise (like for real-time software), it may not be worth the time and
trouble.

Good luck,

--
Martijn
http://www.sereneconcepts.nl
Nov 14 '05 #27
> In my experience, the biggest performance gains can be achieved by
finding the bits in your code that are not just slow but completely
braindamaged slow, and fixing them. Not the kind where you ask "what
is faster: Switch or If", but the kind where you ask yourself "how
could anyone be so stupid to write code that way? "

Learn to find these bits of code and learn to use tools to find them.


Would you care to suggest some? I am always on the look-out for
improvements... (if not in speed and resource consumption, in things like
maintainability).

--
Martijn
http://www.sereneconcepts.nl
Nov 14 '05 #28
In article <42***********************@news.xs4all.nl>,
"Martijn" <su*********************@hot-remove-mail.com> wrote:
In my experience, the biggest performance gains can be achieved by
finding the bits in your code that are not just slow but completely
braindamaged slow, and fixing them. Not the kind where you ask "what
is faster: Switch or If", but the kind where you ask yourself "how
could anyone be so stupid to write code that way? "

Learn to find these bits of code and learn to use tools to find them.


Would you care to suggest some? I am always on the look-out for
improvements... (if not in speed and resource consumption, in things like
maintainability).


Well, lets see... Your compiler's documentation? Does it come with a
debugger, does that have documentation? Does it come with a profiler?
Does that have any documentation?
Nov 14 '05 #29
In article <11********************@o13g2000cwo.googlegroups.c om>,
"forayer" <th********@hotmail.com> wrote:
Christian Bau wrote:
Did you verify your understanding by measuring the actual speed or
looking at code that was generated? I don't think so.


step-by-step execution in a debugger works for me! and yes, the
switch-cases did jump.


You are saying you use a compiler that will use 200 consecutive
comparisons and conditional branches for a switch statement with 200
cases?
Nov 14 '05 #30
In article <d9**********@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com>,
"Malcolm" <re*******@btinternet.com> wrote:
Now if we arrange the if .. else ladder with "Mr" as the first condition,
"Mrs" as the second, and "Queen" as the last condition, then about half the
time if will evaluate only a single condition. Only once will it go all the
way down the ladder when it finds the title for the Elizabeth Windsor.

This could easily be faster than a switch, but may not be.


Hi Malcolm,

nowadays with good branch prediction and heavy penalties for incorrect
prediction in many processors, this becomes less significant. Most of
the cost is in _incorrectly predicted_ branches, and in a switch-like
situation, most often there will be exactly one incorrectly predicted
branch, no matter what you do. You can reduce the number of correctly
predicted branches in between, but they are less significant.
Nov 14 '05 #31
Christian Bau wrote:
You are saying you use a compiler that will use 200 consecutive
comparisons and conditional branches for a switch statement with 200
cases?


no, i meant that the switch statement _didnt_ use 200 comparisions. it
jumped right to the appropriate case. such jumps do make sense for
switch-case structures, but how well can they be compared to an array
of function pointers (assuming that the cases can be easily indexed)?

Nov 14 '05 #32

"Christian Bau" <ch***********@cbau.freeserve.co.uk> wrote
Hi Malcolm,

nowadays with good branch prediction and heavy penalties for incorrect
prediction in many processors, this becomes less significant. Most of
the cost is in _incorrectly predicted_ branches, and in a switch-like
situation, most often there will be exactly one incorrectly predicted
branch, no matter what you do. You can reduce the number of correctly
predicted branches in between, but they are less significant.

That's a good point.
The truth is that I hardly ever do any assembly programming these days, so
you tend to forget what the instruction set is like.
Nov 14 '05 #33
Christian Bau wrote:

In article <d9**********@news.yaako.com>,
"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote:
Oh that's definitely a great idea, I'll try, thanks.


Please. PLEASE. Think about it for a second.

Compilers have been doing this kind of stuff for decades.

If there were any simple method that you could use to replace your
switch statement and make it faster, then your compiler would use it.

Of course, you are always free to spend a few hours writing functions,
setting up an array of function pointers, and so on and so on and the
next guy who will have to maintain your code will be cursing you.
Might be you, anyway.


Why don't you like an array of function pointers?

--
pete
Nov 14 '05 #34

On 20/06/2005 06:50, forayer wrote:
Christian Bau wrote:
You are saying you use a compiler that will use 200 consecutive
comparisons and conditional branches for a switch statement with 200
cases?


no, i meant that the switch statement _didnt_ use 200 comparisions. it
jumped right to the appropriate case. such jumps do make sense for
switch-case structures, but how well can they be compared to an array
of function pointers (assuming that the cases can be easily indexed)?


Well, in assembly it probably resembles an array of "jump" pointers...
If you want to emulate that in C, you just create an array of functions,
since computed goto is not available.

Nov 14 '05 #35

On 20/06/2005 10:42, pete wrote:
Christian Bau wrote:

In article <d9**********@news.yaako.com>,
"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote:
Oh that's definitely a great idea, I'll try, thanks.


Please. PLEASE. Think about it for a second.

Compilers have been doing this kind of stuff for decades.

If there were any simple method that you could use to replace your
switch statement and make it faster, then your compiler would use it.

Of course, you are always free to spend a few hours writing functions,
setting up an array of function pointers, and so on and so on and the
next guy who will have to maintain your code will be cursing you.
Might be you, anyway.


Why don't you like an array of function pointers?


Function pointers are perfect, but I'd say "don't try to beat
the compiler unless there is a good reason". If the targeted compiler does
manage switches well, there is no reason IMHO to use function pointers here.

Nov 14 '05 #36
Jean-Claude Arbaut wrote:
.... snip ...
Well, in assembly it probably resembles an array of "jump"
pointers... If you want to emulate that in C, you just create
an array of functions, since computed goto is not available.


Yes it is. It just happens to be spelled 'switch'.

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
Nov 14 '05 #37

On 20/06/2005 17:21, CBFalconer wrote:
Jean-Claude Arbaut wrote:

... snip ...

Well, in assembly it probably resembles an array of "jump"
pointers... If you want to emulate that in C, you just create
an array of functions, since computed goto is not available.


Yes it is. It just happens to be spelled 'switch'.


Not exactly. A switch has almost the same behaviour, but at assembly level,
(on my implementation) it will be translated as jumps, whereas functions
calls are translated as calls. It has some effect on the stack.
At the C level, there are also differences on scope I suppose.

Nov 14 '05 #38

On 20/06/2005 17:46, Jean-Claude Arbaut wrote:

On 20/06/2005 17:21, CBFalconer wrote:
Jean-Claude Arbaut wrote:

... snip ...

Well, in assembly it probably resembles an array of "jump"
pointers... If you want to emulate that in C, you just create
an array of functions, since computed goto is not available.


Yes it is. It just happens to be spelled 'switch'.


Not exactly. A switch has almost the same behaviour, but at assembly level,
(on my implementation) it will be translated as jumps, whereas functions
calls are translated as calls. It has some effect on the stack.
At the C level, there are also differences on scope I suppose.


And you have no guarantee a C compiler is smart enough to use a jump table.
That's not in the standard ;-) However, it is very likely to be smart
enough.

Nov 14 '05 #39
On Mon, 20 Jun 2005 08:42:31 +0000, pete wrote:

....
Why don't you like an array of function pointers?


It is likely that calling a function will have more overhead than
performing a jump.

Lawrence
Nov 14 '05 #40
Lawrence Kirby <lk****@netactive.co.uk> writes:
On Mon, 20 Jun 2005 08:42:31 +0000, pete wrote:

...
Why don't you like an array of function pointers?


It is likely that calling a function will have more overhead than
performing a jump.


I wouldn't necessarily disagree with that, but here is a data
point. Performance measurements on x86 (that I've done) show
that the cost of a 'switch()' with a dense case set (256 values,
say) is pretty much neck-and-neck with the cost of calling
through pointer-to-function to do the same thing. Depending on
the specifics, calling through pointer-to-function can be faster
than using 'switch()'.

Of course, that assumes other considerations aren't a factor, and
often they are - sometimes favoring using 'switch()', and
sometimes favoring using a function call.
Nov 14 '05 #41
In article <BE******************************@laposte.net>,
Jean-Claude Arbaut <je****************@laposte.net> wrote:
On 20/06/2005 17:46, Jean-Claude Arbaut wrote:

On 20/06/2005 17:21, CBFalconer wrote:
Jean-Claude Arbaut wrote:

... snip ...
Well, in assembly it probably resembles an array of "jump"
pointers... If you want to emulate that in C, you just create
an array of functions, since computed goto is not available.

Yes it is. It just happens to be spelled 'switch'.


Not exactly. A switch has almost the same behaviour, but at assembly level,
(on my implementation) it will be translated as jumps, whereas functions
calls are translated as calls. It has some effect on the stack.
At the C level, there are also differences on scope I suppose.


And you have no guarantee a C compiler is smart enough to use a jump table.
That's not in the standard ;-) However, it is very likely to be smart
enough.


It is also quite likely not to generate a jump table if that is smarter.
The compiler will know how long conditional branches take, how long
branching using a branch table takes, and so on. What if you have
twohundred cases with wildly varying values so you cannot use a jump
table? Some implementations will actually use a hash function in that
case. Or they use if/else arranged in a binary tree.
Nov 14 '05 #42
In article <kf*************@alumnus.caltech.edu>,
Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
Lawrence Kirby <lk****@netactive.co.uk> writes:
On Mon, 20 Jun 2005 08:42:31 +0000, pete wrote:

...
Why don't you like an array of function pointers?
It is likely that calling a function will have more overhead than
performing a jump.


I wouldn't necessarily disagree with that, but here is a data
point. Performance measurements on x86 (that I've done) show
that the cost of a 'switch()' with a dense case set (256 values,
say) is pretty much neck-and-neck with the cost of calling
through pointer-to-function to do the same thing. Depending on
the specifics, calling through pointer-to-function can be faster
than using 'switch()'.


If you use an old compiler on a Pentium 4, you might get very slow code
(if the compiler generates a table with offset in the same memory area
as the actual code; the processor basically throws up if you try to read
data and instructions from nearby memory locations).
Of course, that assumes other considerations aren't a factor, and
often they are - sometimes favoring using 'switch()', and
sometimes favoring using a function call.

Nov 14 '05 #43

On 21/06/2005 02:05, Christian Bau wrote:
In article <BE******************************@laposte.net>,
Jean-Claude Arbaut <je****************@laposte.net> wrote:
On 20/06/2005 17:46, Jean-Claude Arbaut wrote:

On 20/06/2005 17:21, CBFalconer wrote:

Jean-Claude Arbaut wrote:
>
... snip ...

>
> Well, in assembly it probably resembles an array of "jump"
> pointers... If you want to emulate that in C, you just create
> an array of functions, since computed goto is not available.

Yes it is. It just happens to be spelled 'switch'.

Not exactly. A switch has almost the same behaviour, but at assembly level,
(on my implementation) it will be translated as jumps, whereas functions
calls are translated as calls. It has some effect on the stack.
At the C level, there are also differences on scope I suppose.


And you have no guarantee a C compiler is smart enough to use a jump table.
That's not in the standard ;-) However, it is very likely to be smart
enough.


It is also quite likely not to generate a jump table if that is smarter.
The compiler will know how long conditional branches take, how long
branching using a branch table takes, and so on. What if you have
twohundred cases with wildly varying values so you cannot use a jump
table? Some implementations will actually use a hash function in that
case. Or they use if/else arranged in a binary tree.


Well, actually CBFalconer was talking about computed goto, and I completely
missed the point. He was kind enough not to correct me :-)

Nov 14 '05 #44
Jean-Claude Arbaut <je****************@laposte.net> writes:
On 20/06/2005 17:21, CBFalconer wrote:
Jean-Claude Arbaut wrote:

... snip ...

Well, in assembly it probably resembles an array of "jump"
pointers... If you want to emulate that in C, you just create
an array of functions, since computed goto is not available.


Yes it is. It just happens to be spelled 'switch'.


Not exactly. A switch has almost the same behaviour, but at assembly level,
(on my implementation) it will be translated as jumps, whereas functions
calls are translated as calls. It has some effect on the stack.
At the C level, there are also differences on scope I suppose.


I think he meant that a switch statement is essentially the same thing
as a computed goto. (It's a bit more limited (for example you can't
do a backward jump), but that's a good thing.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #45
One way to tackle the problem may be to drill down in a binary search
tree type of manner. For example, Lets say you have cases 0-255. You
could do something like this:

switch (x/100) { /* Check the first digit and drill down. */
case 0:
switch (x/10 - (x/100) * 10) { /* check the second digit. */
case 0:
switch ... /* check the third digit. */
case 1:
... (similar to above)
case 2:
... (similar to above)
... (continue like this through 9)

case 1:
.... (similar to above)
case 2:
.... (similar to above)
default:
/* Error. */
}

So what you are basically doing is checking each digit to find the
value you want. This effectively means that each check on a 0-255 (or
to 999 for that matter) will only involve three checks. The only cases
where a single switch statement will be faster is if the first two
cases were selected most of the time.

Nov 14 '05 #46
In article <11*********************@g14g2000cwa.googlegroups. com> "icub3d" <ic****@gmail.com> writes:
....
So what you are basically doing is checking each digit to find the
value you want. This effectively means that each check on a 0-255 (or
to 999 for that matter) will only involve three checks. The only cases
where a single switch statement will be faster is if the first two
cases were selected most of the time.


Unless the switch is implemented with a jump table.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #47
REH

"icub3d" <ic****@gmail.com> wrote in message
news:11*********************@g14g2000cwa.googlegro ups.com...
One way to tackle the problem may be to drill down in a binary search
tree type of manner. For example, Lets say you have cases 0-255. You
could do something like this:

switch (x/100) { /* Check the first digit and drill down. */
case 0:
switch (x/10 - (x/100) * 10) { /* check the second digit. */
case 0:
switch ... /* check the third digit. */
case 1:
... (similar to above)
case 2:
... (similar to above)
... (continue like this through 9)

case 1:
... (similar to above)
case 2:
... (similar to above)
default:
/* Error. */
}

So what you are basically doing is checking each digit to find the
value you want. This effectively means that each check on a 0-255 (or
to 999 for that matter) will only involve three checks. The only cases
where a single switch statement will be faster is if the first two
cases were selected most of the time.

You are assuming that a single switch statement does multiple checks. I
doubt any implementation does so. So, your "optimization" does three checks
(plus all the math), where as if you just let the compiler do the work,
there is only one.

REH
Nov 14 '05 #48
In article <d9*********@cui1.lmms.lmco.com>, REH <bo***@nowhere.net> wrote:
You are assuming that a single switch statement does multiple checks. I
doubt any implementation does so.


I just created a simple test program with four non-consequative
case labels. SGI's "cc" compiler and gcc generated different looking
code for the same program, but at key points, they both did multiple
comparisons and not just against the boundary values. [Oddly, for
both, the first pair of comparisions they did was against the
first case label and then against the second-largest case label -- not
against the largest.]

--
'The short version of what Walter said is "You have asked a question
which has no useful answer, please reconsider the nature of the
problem you wish to solve".' -- Tony Mantler
Nov 14 '05 #49
Unfortunately, we can't determine ahead of time if the compiler will do
this work for us. As Walter suggested, two major compilers don't do
this optimization, so it's hard to assume that many others will.

Nov 14 '05 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.