Ayende @ Rahien

Refunds available at head office

Can you make this code run any faster?

public static class GuidExtensions
{
    public static Guid TransfromToGuidWithProperSorting(this byte[] bytes)
    {
        return new Guid(new[]
        {
            bytes[10],
            bytes[11],
            bytes[12],
            bytes[13],
            bytes[14],
            bytes[15],
            bytes[8],
            bytes[9],
            bytes[6],
            bytes[7],
            bytes[4],
            bytes[5],
            bytes[0],
            bytes[1],
            bytes[2],
            bytes[3],
        });
    }

    public static byte[] TransformToValueForEsentSorting(this Guid guid)
    {
        var bytes = guid.ToByteArray();
        return new[]
        {
            bytes[12],
            bytes[13],
            bytes[14],
            bytes[15],
            bytes[10],
            bytes[11],
            bytes[8],
            bytes[9],
            bytes[6],
            bytes[7],
            bytes[0],
            bytes[1],
            bytes[2],
            bytes[3],
            bytes[4],
            bytes[5],
        };
    }
}

 

Just to note, this is stupid micro optimization trick, it takes 0.00008 ms to execute right now, which is plenty fast enough, but it is fun to play with it.

Comments

Steve
09/16/2010 10:40 AM by
Steve

public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)

Is the ctor that does no validation (null check + array length check).

configurator
09/16/2010 11:16 AM by
configurator

An unsafe method returning something like

return new Guid(

((int)(bytes+10)),

((short)(bytes+14)),

((short)(bytes+8)),

*(bytes+9),

*(bytes+6),

*(bytes+7),

*(bytes+4),

*(bytes+5),

*(bytes+0),

*(bytes+1),

*(bytes+2),

*(bytes+3))

Would probably be faster - thought I'm not sure if my endianness is correct. Otherwise you'd have to do that casting yourself as it (bytes+13) << 0x18 | ((bytes+12)) << 0x10 | ((bytes+11)) << 0x8 | ((bytes+10))

but it would still probably be just a bit faster

James Newton-King
09/16/2010 11:48 AM by
James Newton-King

In TransformToValueForEsentSorting you could rearrange the values in the array that ToByteArray returns rather than creating a new array.

Bags not writing the code.

Ken Egozi
09/16/2010 11:49 AM by
Ken Egozi

Run it on Linux. They say it's faster.

Ed James
09/16/2010 12:13 PM by
Ed James

Correct spelling is a good way to increase code speed.

TransfromToGuidWithProperSorting

tobi
09/16/2010 01:25 PM by
tobi

According to reflector the most optimal ctor is public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) btw. I cannot believe that it takes 0.08us because that would be only about 12k times a second. I would expect a 100 times that easily.

Frank Quednau
09/16/2010 01:44 PM by
Frank Quednau

@tobi How did you calculate that?

1000 ms / 0.000008 = 125'000'000

Harry Steinhilber
09/16/2010 02:37 PM by
Harry Steinhilber

@Frank,

I think you have an extra 0 in there. It should be 8x10^-5 not 8x10^-6.

@tobi,

Even still, that makes it 12 million times per second, not 12 thousand.

Frank Quednau
09/16/2010 03:01 PM by
Frank Quednau

@Harry That totally stole my thunder :)

Indeed, this code

public static Guid TransfromToGuidWithProperSorting(this byte[] array)

    {

        return new Guid(

            array[10] + (array[11] << 8) + (array[12] << 16) + (array[13] << 24), 

            (short) (array[14] + (array[15] << 8)), 

            (short) (array[8] + (array[9] << 8)), 

            array[6], array[7], array[4], array[5], array[0], array[1], array[2], array[3]);

    }

runs roughly 40-50% faster on my machine in comparison.

I know you aren't the most avid SO user, but putting this up there as performance code golf might get you better responses than here.

tobi
09/16/2010 04:55 PM by
tobi

Harry, "Even still, that makes it 12 million times per second, not 12 thousand." I don't think this is true. 0.001 would be 1k a second, 0.0001 = 10k/second. then mul by 8/10.

Martin
09/16/2010 05:31 PM by
Martin

You probably shouldnt be doing what you are doing, but instead create your own Guid type implementation that knows how to compare (sort properly)

Messing with the Guids internal structure, will make it difficult to read/understand the code as you would have to know about what type of Guid you are dealing with, if it has been changed and how it structured.

Also you dont need the conversion at all, which is even better.

Use Reflector to look at how the SqlGuid is implemented, which is used to compare/sort Comb.Guids correctly (by the last 6 bytes).

http://msdn.microsoft.com/en-us/library/ms254976(VS.80).aspx

Martin :)

Luc
09/16/2010 05:41 PM by
Luc

@tobi

Ayende said 0.00008 MILLISECONDS, not 0.00008 seconds. So adding three orders of magnitude above 12,000 you get...

tobi
09/16/2010 08:33 PM by
tobi

Ah you are right! Well, what an important discussion ;-)

Rik Hemsley
09/17/2010 06:00 PM by
Rik Hemsley

Hmm I recognise the article code ;) Interesting to see the variations.

Comments have been closed on this topic.