This is a list of three examples on how to use uuid-creator to reduce thread contention on Linux.
An additional example uses ulid-creator to generate Monotonic ULIDs and then turn them into RFC-4122 UUID (standard). Monotonic ULID generation is very fast.
The benchmark code is available on a GitHub Gist.
Example 1: using UuidCreator
and SHA1PRNG
How to setup the SHA1PRNG
algorithm to be used by UuidCreator
:
# Append to /etc/environment or ~/.profile
# Use the the algorithm SHA1PRNG for SecureRandom
export UUIDCREATOR_SECURERANDOM="SHA1PRNG"
// generate a random-based UUID
UUID uuid = UuidCreator.getRandomBased();
UuidCreator
uses a fixed pool of SecureRandom
. The variable UUIDCREATOR_SECURERANDOM
tells UuidCreator
to use another SecureRandom
algorithm, instead of NativePRNG
on Linux. UuidCreator
along with SHA1PRNG
algorithm generates UUIDs with less thread contention (less-blocking) than UUID.randomUUID()
.
See the benchmark using 4 threads:
----------------------------------------------------------------------
Benchmark Mode Cnt Score Error Units
----------------------------------------------------------------------
UUID.randomUUID() thrpt 5 1423,060 ± 30,125 ops/ms
UuidCreator.getRandomBased() thrpt 5 10616,016 ± 281,486 ops/ms
----------------------------------------------------------------------
Example 2: using ThreadLocalRandom
How to implement a UUID generator using ThreadLocalRandom
:
public class UuidGenerator {
private static final RandomBasedFactory UUID_FACTORY;
static {
UUID_FACTORY = new RandomBasedFactory((int length) -> {
final byte[] bytes = new byte[length];
ThreadLocalRandom.current().nextBytes(bytes);
return bytes;
});
}
public static UUID generate() {
return UUID_FACTORY.create();
}
}
ThreadLocalRandom
is a fast (and unsafe) random generator without thread contention (non-blocking).
See the benchmark using 4 threads:
----------------------------------------------------------------------
Benchmark Mode Cnt Score Error Units
----------------------------------------------------------------------
UUID.randomUUID() thrpt 5 1423,060 ± 30,125 ops/ms
UuidGenerator.generate() thrpt 5 85390,979 ± 1564,589 ops/ms
----------------------------------------------------------------------
Example 3: using RandomBasedFactory[]
and SHA1PRNG
How to implement a UUID generator using ana array of RandomBasedFactory
and SHA1PRNG
algorithm:
public static class UuidGenerator {
private static final int SIZE = 8; // you choose
private static final RandomBasedFactory[] FACTORIES;
static {
FACTORIES = new RandomBasedFactory[SIZE];
try {
for (int i = 0; i < FACTORIES.length; i++) {
// SHA1PRNG or DRBG can be used to reduce thread contention.
SecureRandom argument = SecureRandom.getInstance("SHA1PRNG");
FACTORIES[i] = new RandomBasedFactory(argument);
}
} catch (NoSuchAlgorithmException e) {
// oops!
}
}
public static UUID generate() {
// calculate the factory index given the current thread ID
final int index = (int) Thread.currentThread().getId() % SIZE;
return FACTORIES[index].create();
}
}
An array of RandomBasedFactory
with and SHA1PRNG
algorithm can generate UUIDs with less thread contention (less-blocking).
See the benchmark using 4 threads:
----------------------------------------------------------------------
Benchmark Mode Cnt Score Error Units
----------------------------------------------------------------------
UUID.randomUUID() thrpt 5 1423,060 ± 30,125 ops/ms
UuidGenerator.generate() thrpt 5 10048,747 ± 195,209 ops/ms
----------------------------------------------------------------------
Example 4: using UlidCreator
and Monotonic ULIDs
How to use ulid-creator to generate RFC-4122 UUIDs from Monotonic ULIDs:
// create a Monotonic ULID and convert it to RFC-4122 UUID v4
UUID uuid = UlidCreator.getMonotonicUlid().toRfc4122().toUuid();
See the benchmark using 4 threads:
-----------------------------------------------------------------------
Benchmark Mode Cnt Score Error Units
-----------------------------------------------------------------------
UUID.randomUUID() thrpt 5 1423,060 ± 30,125 ops/ms
UlidCreator.getMonotonicUlid() thrpt 5 7391,917 ± 871,799 ops/ms
-----------------------------------------------------------------------
EDIT: added the 4th example that uses Monotonic ULID.
Disclaimer: I'm the main contributor of uuid-creator
.