⚠ ARCHIVED. libksuid 1.0.0 is feature-complete and is preserved here as a read-only artifact. Active development continues under a broader scope in libchronoid — a C11 toolkit for time-ordered identifiers that includes both the original KSUID surface (renamed to
chronoid_ksuid_*) and a new UUIDv7 (RFC 9562) implementation as sibling formats under one library.Migration:
- Header path:
<libksuid/ksuid.h>→<chronoid/ksuid.h>- Library / SONAME:
libksuid.so.1→libchronoid.so.0(0.9.x pre-release; SONAME advances when libchronoid cuts 1.0)- pkg-config:
libksuid.pc→libchronoid.pc- CLI:
ksuid-gen→chronoid-gen- Public API:
ksuid_*/KSUID_*→chronoid_ksuid_*/CHRONOID_KSUID_*(semantics unchanged; wire format preserved bytewise)No new commits, issues, or PRs will be accepted on this repository. Existing 1.0.0 consumers may continue to use
libksuid.so.1as shipped; libchronoid does not provide a libksuid.so.1-compatible binary.
A pure C11 port of segmentio/ksuid
focused on small footprint, lock-free thread safety, and SIMD/NEON
acceleration where the underlying algorithms admit it.
1.0.0 — public API and ABI are stable, repository archived
2026-05-01. SONAME is libksuid.so.1; subsequent 1.x releases stay
binary-compatible (semver) but no further releases will be cut from
this repository.
- Pure C11. No pthread; thread safety via
_Thread_localstorage and<stdatomic.h>only. - meson + ninja build. Both static and shared libraries plus a
ksuid-genCLI for round-trip generation and parsing. - Wire-compatible with upstream
segmentio/ksuid— same 20-byte binary layout, same 27-character base62 string encoding, same epoch (1400000000 = 2014-05-13 16:53:20 UTC), same ordering invariants. - Honest SIMD: the base62 long-division core is sequential and is not vectorizable; SSE2/NEON paths accelerate input validation (16-byte packed range tests, sentinel-fill on miss).
- Cross-platform RNG:
- Linux:
getrandom(2)with/dev/urandomfallback - macOS:
getentropy(3)(10.12+) with/dev/urandomfallback - Windows:
BCryptGenRandom(linked viabcrypt.lib) - Per-thread ChaCha20 CSPRNG keyed from the OS source, reseeded every 1 MiB / hour / fork / clock-skew event.
- Linux:
- Small footprint: no heap allocations on the hot path; no third-party runtime dependencies. Stripped library is ~18 KB.
libksuid is distributed under the GNU Lesser General Public License,
version 3 or later (see LICENSE). It is a derivative
work that ports algorithms and binary formats from segmentio/ksuid,
which is distributed under the MIT License (see
LICENSE.MIT for the upstream text). The combined
attribution requirements are described in NOTICE.
Source files derived from upstream Go code carry the SPDX header
SPDX-License-Identifier: LGPL-3.0-or-later AND MIT
and a pointer back to the upstream source they were ported from.
meson setup build
meson compile -C build
meson test -C buildFor a release build with NDEBUG and stripped binaries:
meson setup build-release --buildtype=release
meson compile -C build-release
strip --strip-unneeded build-release/libksuid.so.*A release build on x86_64 produces (post-strip --strip-unneeded):
| Artifact | Bytes |
|---|---|
| libksuid.so.1.0.0 | 26 752 |
| libksuid.a | 35 212 |
| ksuid-gen (CLI) | 22 920 |
The bulk-encode AVX2 kernel from libksuid/encode_avx2.c accounts for
roughly 8 KB of the shared-library size; non-AVX2 hosts compile and
link the kernel but never call into it, so the CPUID-gated dispatch
adds no runtime cost to those targets.
The shared library has zero runtime dependencies beyond the C library
and, on Windows, bcrypt.lib.
$ ksuid-gen
3D3tYHbvwtnqJnHlVV0SnfLhsIl
$ ksuid-gen -n 3
3D3tYDod37FCb5o2znp85EOqeO3
3D3tYG2kSSEmqfHFkSFXeSYyLAa
3D3tYGRMmQOon3PeymhLvYc1yu5
$ ksuid-gen -f inspect 0ujtsYcgvSTl8PAuAdqWYSMnLOv
REPRESENTATION:
String: 0ujtsYcgvSTl8PAuAdqWYSMnLOv
Raw: 0669F7EFB5A1CD34B5F99D1154FB6853345C9735
COMPONENTS:
Time: 2017-10-10 04:00:47 +0000 UTC
Timestamp: 107608047
Payload: B5A1CD34B5F99D1154FB6853345C9735The full flag set is -n N, -f {string,inspect,time,timestamp,payload,raw}, -v, -h. See ksuid-gen -h for details.
The Go upstream's -f template is intentionally not supported -- a
faithful re-implementation of Go's text/template grammar in C is
out of scope, and a "mostly compatible" template engine is worse than
no engine at all.
When formatting many KSUIDs at once (database snapshots, log batches,
network bulk responses), use the bulk variant rather than calling
ksuid_format in a loop:
ksuid_t ids[1024];
char out[1024 * KSUID_STRING_LEN]; /* no NUL terminators */
ksuid_string_batch (ids, out, 1024);
/* ids[i] is now at out[i * KSUID_STRING_LEN .. (i + 1) * KSUID_STRING_LEN - 1] */The function is thread-safe for disjoint output buffers and n == 0
is a no-op. Output is byte-identical to a ksuid_format loop --
only the throughput differs.
The implementation dispatches at first call to a kernel selected from CPU features via an atomic function pointer (libsodium-style trampoline; race-free without locks or allocation):
- x86_64 + AVX2: an 8-wide AVX2 kernel that processes eight
KSUIDs per outer iteration via a Granlund-Möller floor-reciprocal
multiply divide-by-62 (#13).
The magic constant is auto-generated by
tools/derive-magic.py, pinned inlibksuid/divisor_magic.h, and verified against__uint128_tinteger division on every CI run. - Other hosts (non-AVX2 x86_64, aarch64, arm, ...): a per-ID
scalar loop equivalent to calling
ksuid_formatN times.
Output is byte-identical across kernels; the differential parity
test in tests/test_string_batch.c cross-checks the AVX2 kernel
against the scalar reference over ≥ 2²⁰ pseudo-random KSUIDs and a
lane-swap detection corpus.
Setting the environment variable KSUID_FORCE_SCALAR=1 pins the
dispatcher to the scalar path at first call (runtime kill switch
without rebuilding the library).
The repository follows the libsoup-style single-source-directory
convention. All public and private library code lives under
libksuid/, and every C file -- inside the library, in tests, and in
examples -- includes its dependencies with the prefixed form
#include <libksuid/ksuid.h> /* the public umbrella */
#include <libksuid/base62.h> /* internal helper */After install the public header lands at
${prefix}/include/libksuid/ksuid.h, so downstream consumers use the
exact same include line that the in-tree sources do.
libksuid/ library source + headers (public ksuid.h here too)
examples/ example consumers; ksuid-gen CLI
tests/ unit + integration tests
tools/ build tooling (gst-indent)
hooks/ git hooks (pre-commit code-style check)
The KSUID specification, base62 alphabet, encoding scheme, and reference
test vectors all originate from
segmentio/ksuid (MIT License,
Copyright (c) 2017 Segment.io). This project would not exist without
that prior art.