• Stars
    star
    335
  • Rank 122,887 (Top 3 %)
  • Language
    C#
  • License
    MIT License
  • Created almost 8 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

.Net ULID implementation

Logo NUlid

A .Net ULID implementation

Universally Unique Lexicographically Sortable Identifier

A GUID/UUID can be suboptimal for many use-cases because:

  • It isn't the most character efficient way of encoding 128 bits
  • It provides no other information than randomness

A ULID however:

  • Is compatible with UUID/GUID's
  • 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
  • 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)

Installation

PM> Install-Package NUlid

Or simply use the Nuget package manager GUI in Visual Studio.

Usage

Creating a ULID:

// Create a ULID
var myulid = Ulid.NewUlid();
// Print ULID
Console.WriteLine(myulid);

Output:

01ASB2XFCZJY7WHZ2FNRTMQJCT

Parsing a ULID:

// Parse ULID:
var myulid = Ulid.Parse("01ASB2XFCZJY7WHZ2FNRTMQJCT");
// Print time-part of ULID:
Console.WriteLine(myulid.Time);

Output:

4-8-2016 15:31:59 +00:00

You can also convert from/to GUID/UUID's, get the byte-representation of a ULID, create a ULID with specific timestamp and you can even specify an IUlidRng to use for generating the randomness (by default NUlid uses the CSUlidRng but a SimpleUlidRng is also provided, as well as a MonotonicUlidRng). The ULID is implemented as a struct with (operator) overloads for (in)equality, comparison etc. built-in and is, generally, very much like .Net's native Guid struct. An extensive helpfile is provided in the Nuget package and the testsuite also serves as a (simple) demonstration of NUlid's features.

Specification

Below is the current specification of ULID as implemented in this repository.

 01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp          Randomness
  10 chars           16 chars
   48bits             80bits
   base32             base32

Components

Timestamp

  • 48 bit integer
  • UNIX-time in milliseconds
  • Won't run out of space till the year 10895 AD (this .Net specific Ulid implementation limits this to DateTimeOffset.MaxValue).

Randomness

  • 80 (Whenever possible: Cryptographically secure) Random bits

As of v1.4.0 monotonic ULID's are supported (see below).

Monotonicity

When generating a ULID within the same millisecond, it is possible to provide some guarantees regarding sort order (with some caveats). When you use the MonotonicUlidRng and a newly generated ULID in the same millisecond is detected, the random component is incremented by 1 bit in the least significant bit position (with carrying). For example:

// Create monotonic rng
var rng = new MonotonicRng();

// Create ULIDs, assume that these calls occur within the same millisecond:
Console.WriteLine(Ulid.NewUlid(rng)); // 01DBN5W2SG000DCBVYHX4T6MCX
Console.WriteLine(Ulid.NewUlid(rng)); // 01DBN5W2SG000DCBVYHX4T6MCY
Console.WriteLine(Ulid.NewUlid(rng)); // 01DBN5W2SG000DCBVYHX4T6MCZ
Console.WriteLine(Ulid.NewUlid(rng)); // 01DBN5W2SG000DCBVYHX4T6MD0
Console.WriteLine(Ulid.NewUlid(rng)); // 01DBN5W2SG000DCBVYHX4T6MD1
Console.WriteLine(Ulid.NewUlid(rng)); // 01DBN5W2SG000DCBVYHX4T6MD2

By default the most significant bit of the random part is set to zero; this ensures you can generate enough ULID's after the initial one before causing an overflow. Some implementations simply pick a random value for the random part and increment this value, however, there's a (very small) chance that this random part is close to the overflow value. If you then happen to generate a lot of ULID's within the same millisecond there is a risk the you hit the overflow. By our method we ensure there's enough 'room' for new values before 'running out of values' (overflowing). It is, with some effort, even possible to 'resume counting' from any given ULID.

Encoding

Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.

0123456789ABCDEFGHJKMNPQRSTVWXYZ

Binary Layout and Byte Order

The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order).

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      32_bit_uint_time_high                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     16_bit_uint_time_low      |       16_bit_uint_random      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

String Representation

ttttttttttrrrrrrrrrrrrrrrr

Where: t is Timestamp r is Randomness

Prior Art

Based on / inspired by alizain/ulid.

Test Suite

Build status

Performance

Below measurements are based on an Intel(R) Core(TM) i9-10900X CPU @ 3.70Ghz:

BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22621.963)
Intel Core i9-10900X CPU 3.70GHz, 1 CPU, 20 logical and 10 physical cores
.NET SDK=7.0.101
  [Host]     : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2
  DefaultJob : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2


|                               Method |      Mean |    Error |   StdDev |   Gen0 | Allocated |
|------------------------------------- |----------:|---------:|---------:|-------:|----------:|
|                       Guid.NewGuid() |  58.14 ns | 0.334 ns | 0.296 ns |      - |         - |
|          Ulid.NewUlid(SimpleUlidRng) |  50.32 ns | 0.193 ns | 0.171 ns |      - |         - |
|              Ulid.NewUlid(CSUlidRng) | 117.07 ns | 0.862 ns | 0.720 ns |      - |         - |
| Ulid.NewUlid(SimpleMonotonicUlidRng) |  65.02 ns | 0.124 ns | 0.110 ns |      - |         - |
|     Ulid.NewUlid(CSMonotonicUlidRng) |  65.58 ns | 0.119 ns | 0.099 ns |      - |         - |
|                   Guid.Parse(string) | 193.62 ns | 0.813 ns | 0.721 ns | 0.0095 |      96 B |
|                   Ulid.Parse(string) | 226.54 ns | 0.299 ns | 0.250 ns | 0.0181 |     184 B |
|                      Guid.ToString() | 168.76 ns | 0.597 ns | 0.558 ns | 0.0095 |      96 B |
|                      Ulid.ToString() | 144.66 ns | 0.504 ns | 0.447 ns | 0.0079 |      80 B |
|                   'new Guid(byte[])' |  10.96 ns | 0.031 ns | 0.024 ns | 0.0040 |      40 B |
|                   'new Ulid(byte[])' |  12.55 ns | 0.024 ns | 0.021 ns | 0.0040 |      40 B |
|                   Guid.ToByteArray() |  65.32 ns | 0.183 ns | 0.152 ns | 0.0039 |      40 B |
|                   Ulid.ToByteArray() | 127.23 ns | 0.337 ns | 0.298 ns | 0.0038 |      40 B |
|                        Ulid.ToGuid() | 117.48 ns | 0.434 ns | 0.406 ns |      - |         - |
|                     'new Ulid(Guid)' |  64.26 ns | 0.574 ns | 0.537 ns |      - |         - |

More Repositories

1

IdGen

Twitter Snowflake-alike ID generator for .Net
C#
1,142
star
2

TwoFactorAuth

PHP library for Two Factor Authentication (TFA / 2FA)
PHP
1,025
star
3

TwoFactorAuth.Net

.Net library for Two Factor Authentication (TFA / 2FA)
C#
336
star
4

MongoRepository

Repository abstraction layer on top of Official MongoDB C# driver
C#
310
star
5

NIdenticon

NIdenticon is a library for creating simple Identicons
C#
94
star
6

NGeoNames

Inspired by https://github.com/AReallyGoodName/OfflineReverseGeocode
C#
87
star
7

IP2Country

Ip to country mapping
C#
48
star
8

SimpleFeedReader

Easy to use, simple, Syndication feed reader
C#
32
star
9

NPushOver

Full fledged, async, .Net Pushover client
C#
24
star
10

NISOCountries

Always up-to-date (.Net) ISO Country list
C#
23
star
11

DebuggableSelfInstallingService

A Debuggable, Self-Installing Windows Service Template based on James Michael Hare's excellent blogposts
C#
22
star
12

TimeZoneMapper

Library for mapping *N*X TimeZone ID's (e.g. Europe/Amsterdam) to .Net's TimeZoneInfo classes.
C#
18
star
13

ITimer

Provides a testable abstraction and alternative to System.Threading.Timer and System.Timers.Timer. Targets netstandard2.0 and higher.
C#
16
star
14

TextTableBuilder

Simple, opinionated, modern table builder
C#
12
star
15

DSMRParser.Net

DSMR Parser for .Net
C#
9
star
16

HumanoID

Friendly ID generator. Converts integers to words and back.
PHP
7
star
17

NEnvoy

.Net Enphase Envoy client library
C#
7
star
18

2FACLIClient

LastPass 2FA CLI Client
C#
6
star
19

IClock

Provides a testable abstraction and alternative to DateTime.Now / DateTime.UtcNow
C#
6
star
20

DebuggableSelfInstallingOwinService

A Self-hosted OWIN Windows Service project template that is easier to run and debug than the default Windows Service project template
C#
6
star
21

WordClock

Hobby project building a word clock with friends.
C++
5
star
22

RobThree

3
star
23

NaarDeKloot.nl

Repository for NaarDeKloot.nl
CSS
3
star
24

IPNetworkHelper

Provides helper (extension)methods for working with IPNetworks
C#
3
star
25

NetnummersNL

Interactieve kaart van netnummers (kengetallen) in Nederland / Interactive map of area codes for the Netherlands
HTML
2
star
26

SAC9010QC-SAC12010QC

Reverse engineered IR protocol for HomeFit Living / Alaska SAC9010QC/SAC12010QC (NEC 756504012 based) remote control
C++
2
star
27

P1-meter

P1 Meter (Wemos D1 mini) - Serial to HTTP POST. See also https://github.com/RobThree/DSMR.Net
C++
2
star
28

AutoRefreshTokenHttpMessageHandler

A thread-safe implementation of a DelegatingHandler that automatically refreshes the access token when the access token expires whilst **not** serializing all requests.
C#
2
star
29

NuGetProxy

NuGet proxy that allows anonymous access to NuGet servers that require authentication.
C#
2
star
30

NMSSQLReplication

.Net library for retrieving (and managing) MSSQL Replication information
C#
1
star
31

NLog.Targets.Pushover

NLog.Targets.Pushover is a custom target for NLog enabling you to send logging messages to the Pushover service
C#
1
star
32

RSV

.Net library for reading / writing RSV files
C#
1
star
33

HttpNamespaceManager

Paul Wheeler's HttpNamespacemanager - with minor improvements
C#
1
star