Hello There, Guest! Login or Register


switch-statement research
#1
I did some research on the switch-statement as I wanted to know how well it would perform for a big number of cases. It seems like the Pawn authors have fucked up in their implementation, having implemented switch-case matching with O(N) instead of O(log N) performance, which may have some penalties for the new command handler. It's worth investigating further though. We can publish this on a wiki later on.



Switch statements in Pawn[b]

Switch statements are a convenient way to circomvent the need of using large if-else if loops by providing the ability to define cases for certain values. This is a commonly used structure in many scripts, but given Pawn's static nature it's hard to predict what kind of code is going to be created by the compiler.

[b]Syntax


The basic switch definition is as follows:

  switch (condition) { cases }

The condition must be an expression that returns either a numeric or an enum value. The expression follows common syntax rules, so including more advanced processing in here, including the tenery operator, is fine.

Defining cases for the statement can be done based on their value, with one or more values per case. There are three ways of defining values for a case. Single value switches are the advised way of declaring a case: this ensures that no double entries occur and is generally the cleanest option.

  case 1: // single value

Must you use multiple values, then these may be divided using commas. There is no limit to the number of values that may occur in a single case statement. Using multiple values may be a viable option in case you are dealing with mostly similar enum values. Each value will internally be handled as a separate case-statement.

  case 1, 2, 3: // multiple values, separated by a comma

The third was is strongly discouraged in Las Venturas Playground code. By separating two values by two dots, you indicate that all values in that range should be accepted for this case. Proper usage of values, enums or if-else clauses should prevent you from needing this structure. It will create one case-statement for each entry in the list.

  case 1..10: // any value between one and five, inclusive

The last option allows you to define a case which needs to be called if a value is not being handled by any other case. This could be compared to an "else" statement. There may only be one default-statement in the switch, and it must occur as the very last entry.

  default: // all other values

Internal handling

The Pawn compiler maintains a sorted list of all the expanded case-statements found in the switch statement. It creates internal labels using this algorithm:

* Create a label for the jump-case table.
* Process all "case" statements:
  * Create a unique label for the current statement's value.
  * Verify that no other case-statement exists with the current value.
  * Insert the value in the cases-table.
  * Expand the value expression and repeat these steps for each expanded value.
* When existing, process the "default" statement and create a label.
* Build the internal jump-case table, appended after the switch:
  * When a "default" case exists, default to that, otherwise default to skipping the switch altogether.
  * For each sorted expanded case value, register a new entry in the jump-case table.
* Write the exit label to file, closing down the switch statement.

When script execution reaches a switch-statement, it will jump to the switch' jump-case table and default the jumping position to the exit label. The intepreter will run over all cases in a linear fashion, compare each value with the result of the evaluated switch condition's result and jump to that label if it's a hit. This means that switch statements are O(N) in performance, whereas they could be O(log N) given that the table is sorted. Keep this in mind for performance-critical code.
Reply
#2
Attached is a patch which fixes this. I sent it to the Pawn folks :). Yields a 18x performance improvement for big switches.


Attached Files
.diff   pawn-switch.diff (Size: 1.07 KB / Downloads: 5)
Reply
#3
Excellent find!
Quite a smack in the face for the folks such as Y_Less on the SA:MP forums who constantly stress the importance and efficiency of using switch statements. Can't wait for him to say it to me now :P
Reply