Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   switch vs. if... else if. More efficient? (http://www.chiefdelphi.com/forums/showthread.php?t=62157)

evan_wilson 20-01-2008 21:15

switch vs. if... else if. More efficient?
 
Greetings!

I'm programming the code for the CMUCam and serial interface right now and have just begun the portion where I determine the kind of data I am getting from the serial port buffer. I can imagine that this is an intensive process on the controller... so:

would it be more efficient to use a switch statement or an else... else if chain to determine what the next character in the buffer is?

I've read that a switch statement (out of many possibilities) would be more efficient because of compiler's ability to optimize the order of comparisons. But does this apply in the case of C18 2.4?

Thank you!

ebarker 20-01-2008 21:27

Re: switch vs. if... else if. More efficient?
 
The switch statement essentially constructs the same code as a stack of if/then/else statements.

The switch is useful because it is a way of documenting code and representing it as a 1 of n selector.

This is a plenty fast processor for what you are probably going to try and do so I wouldn't worry about it.

Worrying about these types of things for your i/o routines generally isn't necessary as it was say 30 years ago.

EricVanWyk 20-01-2008 21:47

Re: switch vs. if... else if. More efficient?
 
Always optimize for readability. The exceptions to this rule are _very_ few and far between.

slavik262 20-01-2008 23:15

Re: switch vs. if... else if. More efficient?
 
Agreed. Switch is the way to go IMO. But then again it depends on exactly what you're doing.

Trav-O 21-01-2008 11:19

Re: switch vs. if... else if. More efficient?
 
documenting your code is especially important if your the sole student programmer on your team and your about to graduate :)

if thens might give you more control in some situations, but with state comparisons and what not, switches are pretty and convenient

EricVanWyk 21-01-2008 13:19

Re: switch vs. if... else if. More efficient?
 
Quote:

Originally Posted by Trav-O (Post 682742)
documenting your code is especially important if your the sole student programmer on your team and your about to graduate :)

I've been on the recieving end of that situation. All the programming was done by a father/son team. They refused to "share" with any outsiders. They couldn't make it to our regional.

I had to learn how to program the robot by reading a printout of the code in the back of a van on the way to regionals. This nightmare situation was only made worse by their need to shave a clock cycle here and there.

dcbrown 21-01-2008 19:27

Re: switch vs. if... else if. More efficient?
 
Quote:

The switch statement essentially constructs the same code as a stack of if/then/else statements.
Its functionally equivalent code, but in my experience it is seldom literally the same. That's because a switch statement is used with a single control variable that most often covers a packed or marginally sparse value range (that is, has a range of n...m with few if any values skipped).

In the following test you can see using an "if..else if...else if" has a worse case path of 28 instruction and takes a literal approach of comparison. An example of a single test is shown below:

Quote:

058A6 D00A BRA 0x58bc
235: else if (data_type == 11)
058A8 0EFE MOVLW 0xfe
058AA 50DB MOVF 0xfdb, W, ACCESS
058AC 080B SUBLW 0xb
058AE E104 BNZ 0x58b8
Whereas the switch statement uses a different approach in the compiler with all the comparisons up front and uses about 1/2 as many instruction cycles worse case. The more elements in the "if..else if.." sequence, the more efficient the switch generated code is (at least within the C 2.4 compiler).

Code:

240:                      switch (data_type)
 058BC    0EFE    MOVLW 0xfe
 058BE    50DB    MOVF 0xfdb, W, ACCESS
 058C0    0A0B    XORLW 0xb
 058C2    E01A    BZ 0x58f8
 058C4    0A02    XORLW 0x2
 058C6    E015    BZ 0x58f2
 058C8    0A01    XORLW 0x1
 058CA    E010    BZ 0x58ec
 058CC    0A0B    XORLW 0xb
 058CE    E00B    BZ 0x58e6
 058D0    0A01    XORLW 0x1
 058D2    E006    BZ 0x58e0
 058D4    0A03    XORLW 0x3
 058D6    E001    BZ 0x58da
 058D8    D012    BRA 0x58fe
241:                      {


Still other compilers will use a program jump table strategy to get the switch/case down to 4-8 cycles (compiler aligns a jump table on a 256 program word boundary and uses the switch variable to goto the appropriate entry in the table which then does a goto to the specific code entry.

However, both "if..else if.." and switch are good and valid methods without significant difference except for possible readability. The only place it would really matter would be if the code is executed at interrupt level -- then you might be more concerned with code efficiency vs readability.

Code:

221:              void test_ifswitch( unsigned char data_type )
 05852    CFD9    MOVFF 0xfd9, 0xfe6
 05854    FFE6    NOP
 05856    CFE1    MOVFF 0xfe1, 0xfd9
 05858    FFD9    NOP
222:              {
223:              static char counter;
224:             
225:                if (data_type == 1)
 0585A    0EFE    MOVLW 0xfe
 0585C    04DB    DECF 0xfdb, W, ACCESS
 0585E    E104    BNZ 0x5868
226:                counter = 1;
 05860    0105    MOVLB 0x5
 05862    0E01    MOVLW 0x1
 05864    6F68    MOVWF 0x68, BANKED
227:                else if (data_type == 2)
 05866    D02A    BRA 0x58bc
 05868    0EFE    MOVLW 0xfe                                ; if the compiler was "smart", it would realize
 0586A    50DB    MOVF 0xfdb, W, ACCESS              ; the W reg contains data_type-1, therefore
 0586C    0802    SUBLW 0x2                                ; it would need to just -1 to test for == 2
 0586E    E104    BNZ 0x5878                                ; and save two instruction cycles and be closer
                                                                        ; switch code efficiency... but alas
228:                counter = 2;
 05870    0105    MOVLB 0x5
 05872    0E02    MOVLW 0x2
 05874    6F68    MOVWF 0x68, BANKED
229:                else if (data_type == 3)
 05876    D022    BRA 0x58bc
 05878    0EFE    MOVLW 0xfe
 0587A    50DB    MOVF 0xfdb, W, ACCESS
 0587C    0803    SUBLW 0x3
 0587E    E104    BNZ 0x5888
230:                counter = 3;
 05880    0105    MOVLB 0x5
 05882    0E03    MOVLW 0x3
 05884    6F68    MOVWF 0x68, BANKED
231:                else if (data_type == 8)
 05886    D01A    BRA 0x58bc
 05888    0EFE    MOVLW 0xfe
 0588A    50DB    MOVF 0xfdb, W, ACCESS
 0588C    0808    SUBLW 0x8
 0588E    E104    BNZ 0x5898
232:                counter = 8;
 05890    0105    MOVLB 0x5
 05892    0E08    MOVLW 0x8
 05894    6F68    MOVWF 0x68, BANKED
233:                else if (data_type == 9)
 05896    D012    BRA 0x58bc
 05898    0EFE    MOVLW 0xfe
 0589A    50DB    MOVF 0xfdb, W, ACCESS
 0589C    0809    SUBLW 0x9
 0589E    E104    BNZ 0x58a8
234:                counter = 9;
 058A0    0105    MOVLB 0x5
 058A2    0E09    MOVLW 0x9
 058A4    6F68    MOVWF 0x68, BANKED
235:                else if (data_type == 11)
 058A6    D00A    BRA 0x58bc
 058A8    0EFE    MOVLW 0xfe
 058AA    50DB    MOVF 0xfdb, W, ACCESS
 058AC    080B    SUBLW 0xb
 058AE    E104    BNZ 0x58b8
236:                counter = 11;
 058B0    0105    MOVLB 0x5
 058B2    0E0B    MOVLW 0xb
 058B4    6F68    MOVWF 0x68, BANKED
237:                else
 058B6    D002    BRA 0x58bc
238:                counter = -1;
 058B8    0105    MOVLB 0x5
 058BA    6968    SETF 0x68, BANKED
239:             
240:                switch (data_type)
 058BC    0EFE    MOVLW 0xfe
 058BE    50DB    MOVF 0xfdb, W, ACCESS
 058C0    0A0B    XORLW 0xb
 058C2    E01A    BZ 0x58f8
 058C4    0A02    XORLW 0x2
 058C6    E015    BZ 0x58f2
 058C8    0A01    XORLW 0x1
 058CA    E010    BZ 0x58ec
 058CC    0A0B    XORLW 0xb
 058CE    E00B    BZ 0x58e6
 058D0    0A01    XORLW 0x1
 058D2    E006    BZ 0x58e0
 058D4    0A03    XORLW 0x3
 058D6    E001    BZ 0x58da
 058D8    D012    BRA 0x58fe
241:                {
242:                case 1: counter = 1; break;
 058DA    0E01    MOVLW 0x1
 058DC    6F68    MOVWF 0x68, BANKED
 058DE    D010    BRA 0x5900
243:                case 2: counter = 2; break;
 058E0    0E02    MOVLW 0x2
 058E2    6F68    MOVWF 0x68, BANKED
 058E4    D00D    BRA 0x5900
244:                case 3: counter = 3; break;
 058E6    0E03    MOVLW 0x3
 058E8    6F68    MOVWF 0x68, BANKED
 058EA    D00A    BRA 0x5900
245:                case 8: counter = 8; break;
 058EC    0E08    MOVLW 0x8
 058EE    6F68    MOVWF 0x68, BANKED
 058F0    D007    BRA 0x5900
246:                case 9: counter = 9; break;
 058F2    0E09    MOVLW 0x9
 058F4    6F68    MOVWF 0x68, BANKED
 058F6    D004    BRA 0x5900
247:                case 11: counter = 11; break;
 058F8    0E0B    MOVLW 0xb
 058FA    6F68    MOVWF 0x68, BANKED
 058FC    D001    BRA 0x5900
248:                default: counter = -1;
 058FE    6968    SETF 0x68, BANKED
249:                }
250:              }
 05900    52E5    MOVF 0xfe5, F, ACCESS
 05902    CFE7    MOVFF 0xfe7, 0xfd9
 05904    FFD9    NOP
 05906    0012    RETURN 0



All times are GMT -5. The time now is 23:12.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi