Skip to content

A struct based, no alloc implementation of KSUID, with Ksuids sortable based on the order they were created.

Notifications You must be signed in to change notification settings

michaeldileo/StructKsuid

 
 

Repository files navigation

StructKsuid

An implementation of the segment.io ksuid, a K-sortable unique identifier, but as a struct and with 0 allocations.

The KSUID is sortable lexically (ToString()) and as an object.

Why was this made

There are two other dotnet implementations of KSUID that are popular, Ksuid.Net and DotKsuid. However, I have a use case where I need to create a lot of KSUIDs in succession and have those be lexically sortable based on the order in which they were created.

The GO implementation from segment.io has a next method that takes a ksuid and returns the next one. I modeled my implementation off of this so that one can call Ksuid.NextKsuid() in succession and each result will be sortable based on the order in which they were created.

I also exposed a Ksuid.RandomKsuid() that gives a Ksuid with the timestamp and a random payload.

Differences with the original and other libs

Besides being a struct and no-alloc, the data is stored as uint timestamp, ulong a, ulong b instead of as a timestamp and/or byte array. In doing so, the bytes for the timestamp are no longer switched for endianness as they are in the other implementations. Thus, I can't guarantee that bytes made by other libraries would be compatible here.

Performance

Performance is pretty strong, coming in at about 10x the speed of Ksuid.Net and just a bit slower DotKsuid. The only allocations made are when calling ToString(). I suspect that part of the reason for DotKsuid coming in slightly faster is that this implementation has to copy the 3 parts of the payload instead of passing the reference to the byte array.

Creating a new Ksuid

Parsing

Usage

I tried to keep the API close to the dotnet Guid API.

var ksuid = Ksuid.NextKsuid() // Creates a new Ksuid that is sortable from the last one created

var ksuid = Ksuid.RandomKsuid() // Creates an "untracked" ksuid with the current timestamp and a random payload. Not guaranteed to be sortable from the last, except by timestamp.

var ksuid = Ksuid.FromTimestamp(DateTime | uint) // Similar to RandomKsuid, but with a given timestamp

var ksuid = Ksuid.FromBytes()

var bytes = ksuid.GetBytes()

var timestampUtc = ksuid.TimestampUtc

Ksuid implements IComparable and IEquatable, and has the == and != operators.
ksuida.CompareTo(ksuidb)
ksuida.Equals(ksuidb)
ksuida == ksuidb

Cautions

I did not make a serializer for this Ksuid.

Also be sure that when sorting the strings in dotnet, that the sorting is case sensitive. I had to add do ....OrderBy(string => string, StringComparison.Ordinal) to get the text to be sorted correctly, because the default comparer is case-insensitive. You can see this in the unit tests.

About

A struct based, no alloc implementation of KSUID, with Ksuids sortable based on the order they were created.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%