[Mono-bugs] [Bug 655380] String switch statement 2x slower if compared to simple list of if statements

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Sat Nov 27 13:33:41 EST 2010


https://bugzilla.novell.com/show_bug.cgi?id=655380

https://bugzilla.novell.com/show_bug.cgi?id=655380#c19


Kornél Pál <kornelpal at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kornelpal at gmail.com

--- Comment #19 from Kornél Pál <kornelpal at gmail.com> 2010-11-27 18:33:38 UTC ---
MS csc does the following three things:
- ldstr and IsInterned (1.x only, basically native hashtable lookup)
- op_Equality comparisons (small number of strings)
- Dictionary (more than 6 strings)

Since all string cases has to be constant generating prefect hash functions
could be a solution that however adds considerable extra complexity so may not
be reasonable to implement.

On the other hand something like that could be implemented:
- create a switch on the string length
- if there are multiple cases of the same length create a sub-switch based on
the first character index that is different in each string
- finally compare the whole string

This should work in most cases but the compiler could fall back to the current
Hashtable/comparison implementation when this optimization is not possible.

An example:
switch (s)
{
case "a":
    break;
case "ab":
    break;
case "aaa":
    break;
case "abc":
    break;
case "acc":
    break;
case "adf":
    break;
default:
    throw new NotImplementedException();
}

Could be transformed to this:
if (s == null)
    goto defaultCase;
switch (s.Length)
{
case 1:
    if (s != "a")
        goto defaultCase;
    goto endSwitch;
case 2:
    if (s != "ab")
        goto defaultCase;
    goto endSwitch;
case 3:
    switch (s[1])
    {
    case 'a':
        if (s != "aaa")
            goto defaultCase;
        goto endSwitch;
    case 'b':
        if (s != "abc")
            goto defaultCase;
        goto endSwitch;
    case 'c':
        if (s != "acc")
            goto defaultCase;
        goto endSwitch;
    case 'd':
        if (s != "adf")
            goto defaultCase;
        goto endSwitch;
    }
    break;
}
defaultCase:
throw new NotImplementedException();
endSwitch:;

Note that I haven't done any performance testing I just expect it to be more
efficient for relatively large strings since the full string is being walked
only once.

When lengths/characters are too far from each other and switch is transformed
to ifs there may be no gain from the above transformation.

-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.


More information about the mono-bugs mailing list