Search code examples
c#performance

Fastest way to make a hashkey of multiple strings


The history why is long, but the problem is simple. Having 3 strings I need to cache the matching value. To have a fast cache I use the following code:

public int keygen(string a, string b, string c)
    {
        var x = a + "@@" + b + "@@" + c;
        var hash = x.GetHashCode();
        return hash;
    }

(Note that string a,b,c does not contain the code "@@") The cache it self is just a Dictionary<int, object>

I know there is a risk that the hash key might be non unique, but except this:

Does anyone know a faster way to make an int key? (in C#) This operation takes ~15% of total CPU time and this is a long running app.

I have tried a couple of implementations but failed to find any faster.


Solution

  • Instead of concatenating strings (which creates new strings) you could use XOR or even better simple maths (credits to J.Skeet):

    public int keygen(string a, string b, string c)
    {
        unchecked // Overflow is fine, just wrap
        {
            int hash = 17;
            hash = hash * 23 + a == null ? 0 : a.GetHashCode();
            hash = hash * 23 + b == null ? 0 : b.GetHashCode();
            hash = hash * 23 + c == null ? 0 : c.GetHashCode();
            return hash;
        }
    }
    

    In general it's not necessary to produce unique hashs. But you should minimize collisions.

    Another(not as efficient) way is to use an anonymous type which has a builtin support for GetHashCode:

    public int keygen(string a, string b, string c)
    {
        return new { a, b, c }.GetHashCode();
    }
    

    Note that the name, type and order matters for the calculation of the hashcode of an anonymous type.