How would you make this switch statement as fast as possible?

后端 未结 21 2030
别那么骄傲
别那么骄傲 2021-01-30 04:17

2009-12-04 UPDATE: For profiling results on a number of the suggestions posted here, see below!


The Question

Consider the following very

相关标签:
21条回答
  • 2021-01-30 04:44

    You can get a mild speed-up by ordering the codes according to which ones are most used.

    But I agree with Cletus: the best speed-up I can think of would be to use a hash map with plenty of room (so that there are no collisions.)

    0 讨论(0)
  • 2021-01-30 04:45

    Can we cast the ActivCode to int and then use int in our case statements?

    0 讨论(0)
  • 2021-01-30 04:46

    I'd roll my own fast hash function and use an integer switch statement to avoid string comparisons:

    int  h = 0;  
    
    // Compute fast hash: A[0] + A[1]*0x100
    if (ActivCode.Length > 0)
        h += (int) ActivCode[0];
    if (ActivCode.Length > 1)
        h += (int) ActivCode[1] << 8;  
    
    // Find a match
    switch (h)
    {
        case 0x0000:  return MarketDataExchange.NBBO;        // ""
        case 0x0041:  return MarketDataExchange.AMEX;        // "A"
        case 0x0042:  return MarketDataExchange.BSE;         // "B"
        case 0x5442:  return MarketDataExchange.BATS;        // "BT"
        case 0x0043:  return MarketDataExchange.NSE;         // "C"
        case 0x574D:  return MarketDataExchange.CHX;         // "MW"
        case 0x004E:  return MarketDataExchange.NYSE;        // "N"
        case 0x4150:  return MarketDataExchange.ARCA;        // "PA"
        case 0x0051:  return MarketDataExchange.NASDAQ;      // "Q"
        case 0x4451:  return MarketDataExchange.NASDAQ_ADF;  // "QD"
        case 0x0057:  return MarketDataExchange.CBOE;        // "W"
        case 0x0058:  return MarketDataExchange.PHLX;        // "X"
        case 0x0059:  return MarketDataExchange.DIRECTEDGE;  // "Y"
        default:      return MarketDataExchange.NONE;
    }
    

    My tests show that this is about 4.5 times faster than the original code.

    If C# had a preprocessor, I'd use a macro to form the case constants.

    This technique is faster than using a hash table and certainly faster than using string comparisons. It works for up to four-character strings with 32-bit ints, and up to 8 characters using 64-bit longs.

    0 讨论(0)
  • 2021-01-30 04:49

    Do you have any statistics on which strings are more common? So that those could be checked first?

    0 讨论(0)
  • 2021-01-30 04:49

    Put the cases in a sorted structure with non linear access (like a hash table). The switch that you have will have a linear time.

    0 讨论(0)
  • 2021-01-30 04:51

    Messy but using a combination of nested ifs and hard coding might just beat the optimiser:-

       if (ActivCode < "N") {
             // "" to "MW"
             if (ActiveCode < "BT") {
                // "" to "B"
                if (ActiveCode < "B") {
                    // "" or "A"
                    if (ActiveCode < "A") {
                          // must be ""
                         retrun MarketDataExchange.NBBO;
                    } else {
                         // must be "A"
                        return MarketDataExchange.AMEX;
                    }
                } else {
                    // must be "B"
                    return MarketDataExchange.BSE;
                }
             } else {
                // "BT" to "MW"
                if (ActiveCode < "MW") {
                    // "BT" or "C"
                    if (ActiveCode < "C") {
                          // must be "BT"
                         retrun MarketDataExchange.NBBO;
                    } else {
                         // must be "C"
                        return MarketDataExchange.NSE;
                    }
                } else {
                // must be "MV"
                    return MarketDataExchange.CHX;
                }
             }
        } else {
            // "N" TO "Y"
             if (ActiveCode < "QD") {
                // "N" to "Q"
                if (ActiveCode < "Q") {
                    // "N" or "PA"
                    if (ActiveCode < "PA") {
                          // must be "N"
                         retrun MarketDataExchange.NYSE;
                    } else {
                         // must be "PA"
                        return MarketDataExchange.ARCA;
                    }
                } else {
                    // must be "Q"
                    return MarketDataExchange.NASDAQ;
                }
             } else {
                // "QD" to "Y"
                if (ActiveCode < "X") {
                    // "QD" or "W"
                    if (ActiveCode < "W") {
                          // must be "QD"
                         retrun MarketDataExchange.NASDAQ_ADF;
                    } else {
                         // must be "W"
                        return MarketDataExchange.CBOE;
                    }
                } else {
                // "X" or "Y"
                    if (ActiveCode < "Y") {
                          // must be "X"
                         retrun MarketDataExchange.PHLX;
                    } else {
                         // must be "Y"
                        return MarketDataExchange.DIRECTEDGE;
                    }
                }
             }
        }
    

    This gets the right function with three or four compares. I wouldnt even think of doing this for real unless your piece of code is expected to run several times a second!

    You further otimise it so that only single character compares occurred. e.g. replace '< "BT" ' with '>= "B" ' -- ever so slightly faster and even less readable!

    0 讨论(0)
提交回复
热议问题