VSoft.Ulid - A Universally Unique Lexicographically Sortable Identifier

Hi All

I created a Delphi implementation of ULID - A Universally Unique Lexicographically Sortable Identifier. ULID’s are a better option than GUIDs where sorting is needed

  • 128-bit compatibility with UUID
  • 1.21e+24 unique ULIDs per millisecond
  • Lexicographically sortable!
  • Canonically encoded as a 26 character string, as opposed to the 36 character UUID
  • Uses Crockford’s base32 for better efficiency and readability (5 bits per character)
  • Case insensitive
  • No special characters (URL safe)
  • Monotonic sort order (correctly detects and handles the same millisecond)

Benchmarks

32bit
tulid-bm32

64bit

tulid-bm64

4 Likes

@sglienke had a look at my :poop: code and with few suggestions it’s now a lot faster - even with some added validation to the base32 strings passed to the parse method.

D 11.3 - 32bit
-------------------------------------------------------------------
Benchmark                         Time             CPU   Iterations
-------------------------------------------------------------------
TUlid.Create                   52.1 ns         51.6 ns     10000000
TUlid.Parse - AnsiString       28.4 ns         28.5 ns     23578947
TUlid.Parse                    33.7 ns         33.0 ns     20363636
TUlid.ToString                 32.0 ns         32.5 ns     23578947
D 11.3 64bit
-------------------------------------------------------------------
Benchmark                         Time             CPU   Iterations
-------------------------------------------------------------------
TUlid.Create                   10.9 ns         11.0 ns     64000000
TUlid.Parse - AnsiString       28.1 ns         28.5 ns     23578947
TUlid.Parse                    29.2 ns         29.5 ns     24888889
TUlid.ToString                 29.4 ns         29.3 ns     22400000
D12.1 32bit
-------------------------------------------------------------------
Benchmark                         Time             CPU   Iterations
-------------------------------------------------------------------
TUlid.Create                   51.2 ns         51.6 ns     10000000
TUlid.Parse - AnsiString       28.5 ns         28.3 ns     24888889
TUlid.Parse                    30.2 ns         30.5 ns     23578947
TUlid.ToString                 30.2 ns         29.3 ns     22400000
D 12.1 64bit
-------------------------------------------------------------------
Benchmark                         Time             CPU   Iterations
-------------------------------------------------------------------
TUlid.Create                   8.94 ns         8.79 ns     74666667
TUlid.Parse - AnsiString       28.1 ns         28.5 ns     26352941
TUlid.Parse                    32.8 ns         32.2 ns     21333333
TUlid.ToString                 33.0 ns         33.0 ns     20363636
3 Likes

That made me laugh. I used to do a talk for the ukDevGroup once a year where I would show some code and encourage the attendees to should “That’s :poop:”, but then they had to suggest how to improve it. So to be clear. this is an alternative to GUID for databases. … and the of “Lexicographically sortable!” - i.e. what does it actually mean?

1 Like

lol

If Marco Cantú is The God Of Delphi then Stefan is Delphi Jesus - he frequently does the code equivalent of turning water into wine.

[Apologies to any Christians offended by the allegorical comparison]

3 Likes

It’s a fancy way of saying you can use them for a primary key, and the order makes sense when sorted. The timestamp component is what gives it the order.

Sorting guids is pointless.

1 Like

Stefan understands x86/64 assembly really well (and the performance of instructions) - and spends a lot of time looking at the code generated by the delphi compilers - so he was able to give advice on a few things that impact performance. The net result was going from 16M generations p/s to 100M p/s (x64). Pretty impressive. I told him he should write a book!

3 Likes

This is a good explainer

3 Likes