Updated UlidBasedGuidCreator

This commit is contained in:
Fabio Lima 2020-03-16 00:27:32 -03:00
parent eb65ed35b1
commit ffffe2af51
7 changed files with 92 additions and 36 deletions

View File

@ -18,12 +18,6 @@ Create a ULID as GUID object:
UUID ulid = UlidCreator.getGuid(); UUID ulid = UlidCreator.getGuid();
``` ```
Create a ULID as byte sequence:
```java
byte[] ulid = UlidCreator.getBytes();
```
### Maven dependency ### Maven dependency
Add these lines to your `pom.xml`. Add these lines to your `pom.xml`.

View File

@ -45,7 +45,7 @@ public class UlidCreator {
* @return a GUID * @return a GUID
*/ */
public static UUID getUlid() { public static UUID getUlid() {
return GuidCreatorLazyHolder.INSTANCE.createGuid(); return GuidCreatorLazyHolder.INSTANCE.create();
} }
/** /**
@ -54,7 +54,7 @@ public class UlidCreator {
* @return a GUID * @return a GUID
*/ */
public static UUID getFastUlid() { public static UUID getFastUlid() {
return FastGuidCreatorLazyHolder.INSTANCE.createGuid(); return FastGuidCreatorLazyHolder.INSTANCE.create();
} }
/** /**
@ -86,15 +86,15 @@ public class UlidCreator {
* *
* @return a {@link UlidBasedGuidCreator} * @return a {@link UlidBasedGuidCreator}
*/ */
public static UlidBasedGuidCreator getGuidCreator() { public static UlidBasedGuidCreator getUlidBasedCreator() {
return new UlidBasedGuidCreator(); return new UlidBasedGuidCreator();
} }
private static class GuidCreatorLazyHolder { private static class GuidCreatorLazyHolder {
static final UlidBasedGuidCreator INSTANCE = getGuidCreator(); static final UlidBasedGuidCreator INSTANCE = getUlidBasedCreator();
} }
private static class FastGuidCreatorLazyHolder { private static class FastGuidCreatorLazyHolder {
static final UlidBasedGuidCreator INSTANCE = getGuidCreator().withFastRandomGenerator(); static final UlidBasedGuidCreator INSTANCE = getUlidBasedCreator().withFastRandomGenerator();
} }
} }

View File

@ -124,7 +124,7 @@ public class UlidBasedGuidCreator {
* @throws UlidCreatorException an overrun exception if too many requests are * @throws UlidCreatorException an overrun exception if too many requests are
* made within the same millisecond. * made within the same millisecond.
*/ */
public synchronized UUID createGuid() { public synchronized UUID create() {
final long timestamp = this.getTimestamp(); final long timestamp = this.getTimestamp();
@ -143,7 +143,7 @@ public class UlidBasedGuidCreator {
* @return a ULID string * @return a ULID string
*/ */
public synchronized String createString() { public synchronized String createString() {
UUID guid = createGuid(); UUID guid = create();
return UlidUtil.fromUuidToUlid(guid); return UlidUtil.fromUuidToUlid(guid);
} }

View File

@ -42,29 +42,29 @@ public class Benchmarks {
@Benchmark @Benchmark
@BenchmarkMode(Mode.Throughput) @BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS) @OutputTimeUnit(TimeUnit.MILLISECONDS)
public String getUlidThroughput() { public String getUlidStringThroughput() {
return UlidCreator.getUlid(); return UlidCreator.getUlidString();
} }
@Benchmark @Benchmark
@BenchmarkMode(Mode.AverageTime) @BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS) @OutputTimeUnit(TimeUnit.NANOSECONDS)
public String getUlidAverage() { public String getUlidStringAverage() {
return UlidCreator.getUlid(); return UlidCreator.getUlidString();
} }
@Benchmark @Benchmark
@BenchmarkMode(Mode.Throughput) @BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS) @OutputTimeUnit(TimeUnit.MILLISECONDS)
public UUID getGuidThroughput() { public UUID getUlidThroughput() {
return UlidCreator.getGuid(); return UlidCreator.getUlid();
} }
@Benchmark @Benchmark
@BenchmarkMode(Mode.AverageTime) @BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS) @OutputTimeUnit(TimeUnit.NANOSECONDS)
public UUID getGuidAverage() { public UUID getUlidAverage() {
return UlidCreator.getGuid(); return UlidCreator.getUlid();
} }
@Benchmark @Benchmark

View File

@ -95,10 +95,10 @@ public class UniquenessTest {
// Request a UUID // Request a UUID
UUID uuid = null; UUID uuid = null;
try { try {
uuid = creator.createGuid(); uuid = creator.create();
} catch (UlidCreatorException e) { } catch (UlidCreatorException e) {
// Ignore the overrun exception and try again // Ignore the overrun exception and try again
uuid = creator.createGuid(); uuid = creator.create();
} }
if (verbose) { if (verbose) {
@ -125,7 +125,7 @@ public class UniquenessTest {
} }
public static void execute(boolean verbose, int threadCount, int requestCount) { public static void execute(boolean verbose, int threadCount, int requestCount) {
UlidBasedGuidCreator creator = UlidCreator.getGuidCreator() UlidBasedGuidCreator creator = UlidCreator.getUlidBasedCreator()
.withTimestampStrategy(new FixedTimestampStretegy(System.currentTimeMillis())); .withTimestampStrategy(new FixedTimestampStretegy(System.currentTimeMillis()));
UniquenessTest test = new UniquenessTest(threadCount, requestCount, creator, verbose); UniquenessTest test = new UniquenessTest(threadCount, requestCount, creator, verbose);

View File

@ -1,19 +1,36 @@
package com.github.f4b6a3.ulid; package com.github.f4b6a3.ulid;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import com.github.f4b6a3.ulid.UlidCreator; import com.github.f4b6a3.ulid.UlidCreator;
import com.github.f4b6a3.ulid.creator.UlidBasedGuidCreator;
import com.github.f4b6a3.ulid.util.UlidUtil; import com.github.f4b6a3.ulid.util.UlidUtil;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class UlidCreatorTest { public class UlidCreatorTest {
private static int processors;
private static final int ULID_LENGTH = 26; private static final int ULID_LENGTH = 26;
private static final int DEFAULT_LOOP_MAX = 100_000; private static final int DEFAULT_LOOP_MAX = 100_000;
private static final String DUPLICATE_UUID_MSG = "A duplicate ULID was created";
@BeforeClass
public static void beforeClass() {
processors = Runtime.getRuntime().availableProcessors();
if (processors < 4) {
processors = 4;
}
}
@Test @Test
public void testGetUlid() { public void testGetUlid() {
String[] list = new String[DEFAULT_LOOP_MAX]; String[] list = new String[DEFAULT_LOOP_MAX];
@ -73,4 +90,49 @@ public class UlidCreatorTest {
} }
} }
@Test
public void testGetUlidBasedGuidParallelGeneratorsShouldCreateUniqueUuids() throws InterruptedException {
Thread[] threads = new Thread[processors];
TestThread.clearHashSet();
// Instantiate and start many threads
for (int i = 0; i < processors; i++) {
threads[i] = new TestThread(UlidCreator.getUlidBasedCreator(), DEFAULT_LOOP_MAX);
threads[i].start();
}
// Wait all the threads to finish
for (Thread thread : threads) {
thread.join();
}
// Check if the quantity of unique UUIDs is correct
assertTrue(DUPLICATE_UUID_MSG, TestThread.hashSet.size() == (DEFAULT_LOOP_MAX * processors));
}
private static class TestThread extends Thread {
private static Set<UUID> hashSet = new HashSet<>();
private UlidBasedGuidCreator creator;
private int loopLimit;
public TestThread(UlidBasedGuidCreator creator, int loopLimit) {
this.creator = creator;
this.loopLimit = loopLimit;
}
public static void clearHashSet() {
hashSet = new HashSet<>();
}
@Override
public void run() {
for (int i = 0; i < loopLimit; i++) {
synchronized (hashSet) {
hashSet.add(creator.create());
}
}
}
}
} }

View File

@ -25,10 +25,10 @@ public class UlidBasedGuidCreatorTest {
UlidBasedGuidCreatorMock creator = new UlidBasedGuidCreatorMock(TIMESTAMP); UlidBasedGuidCreatorMock creator = new UlidBasedGuidCreatorMock(TIMESTAMP);
creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP)); creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP));
UUID uuid = creator.createGuid(); UUID uuid = creator.create();
long firstMsb = creator.extractRandomMsb(uuid); long firstMsb = creator.extractRandomMsb(uuid);
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
uuid = creator.createGuid(); uuid = creator.create();
} }
@ -37,7 +37,7 @@ public class UlidBasedGuidCreatorTest {
assertEquals(String.format("The last MSB should be iqual to the first %s.", expectedMsb), expectedMsb, lastMsb); assertEquals(String.format("The last MSB should be iqual to the first %s.", expectedMsb), expectedMsb, lastMsb);
creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP + 1)); creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP + 1));
uuid = creator.createGuid(); uuid = creator.create();
lastMsb = uuid.getMostSignificantBits(); lastMsb = uuid.getMostSignificantBits();
assertNotEquals("The last MSB should be random after timestamp changed.", firstMsb, lastMsb); assertNotEquals("The last MSB should be random after timestamp changed.", firstMsb, lastMsb);
} }
@ -48,10 +48,10 @@ public class UlidBasedGuidCreatorTest {
UlidBasedGuidCreatorMock creator = new UlidBasedGuidCreatorMock(TIMESTAMP); UlidBasedGuidCreatorMock creator = new UlidBasedGuidCreatorMock(TIMESTAMP);
creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP)); creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP));
UUID uuid = creator.createGuid(); UUID uuid = creator.create();
long firstLsb = creator.extractRandomLsb(uuid); long firstLsb = creator.extractRandomLsb(uuid);
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
uuid = creator.createGuid(); uuid = creator.create();
} }
long lastLsb = creator.extractRandomLsb(uuid); long lastLsb = creator.extractRandomLsb(uuid);
@ -60,7 +60,7 @@ public class UlidBasedGuidCreatorTest {
long notExpected = firstLsb + DEFAULT_LOOP_MAX + 1; long notExpected = firstLsb + DEFAULT_LOOP_MAX + 1;
creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP + 1)); creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP + 1));
uuid = creator.createGuid(); uuid = creator.create();
lastLsb = uuid.getLeastSignificantBits(); lastLsb = uuid.getLeastSignificantBits();
assertNotEquals("The last LSB should be random after timestamp changed.", notExpected, lastLsb); assertNotEquals("The last LSB should be random after timestamp changed.", notExpected, lastLsb);
} }
@ -75,7 +75,7 @@ public class UlidBasedGuidCreatorTest {
UUID uuid = new UUID(0, 0); UUID uuid = new UUID(0, 0);
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
uuid = creator.createGuid(); uuid = creator.create();
} }
long expectedLsb = lsb + DEFAULT_LOOP_MAX; long expectedLsb = lsb + DEFAULT_LOOP_MAX;
@ -96,7 +96,7 @@ public class UlidBasedGuidCreatorTest {
UUID uuid = new UUID(0, 0); UUID uuid = new UUID(0, 0);
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) { for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
uuid = creator.createGuid(); uuid = creator.create();
} }
long expectedMsb = msb; long expectedMsb = msb;
@ -120,11 +120,11 @@ public class UlidBasedGuidCreatorTest {
creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP)); creator.withTimestampStrategy(new FixedTimestampStretegy(TIMESTAMP));
for (int i = 0; i < DEFAULT_LOOP_MAX - 1; i++) { for (int i = 0; i < DEFAULT_LOOP_MAX - 1; i++) {
creator.createGuid(); creator.create();
} }
try { try {
creator.createGuid(); creator.create();
fail("It should throw an overflow exception."); fail("It should throw an overflow exception.");
} catch (UlidCreatorException e) { } catch (UlidCreatorException e) {
// success // success
@ -147,7 +147,7 @@ public class UlidBasedGuidCreatorTest {
UUID uuid = new UUID(0, 0); UUID uuid = new UUID(0, 0);
for (int i = 0; i < DEFAULT_LOOP_MAX - 1; i++) { for (int i = 0; i < DEFAULT_LOOP_MAX - 1; i++) {
uuid = creator.createGuid(); uuid = creator.create();
} }
long expectedLsb = (lsbMax - 1) & UlidBasedGuidCreatorMock.HALF_RANDOM_COMPONENT; long expectedLsb = (lsbMax - 1) & UlidBasedGuidCreatorMock.HALF_RANDOM_COMPONENT;
@ -159,7 +159,7 @@ public class UlidBasedGuidCreatorTest {
assertEquals("Incorrect MSB after loop.", expectedMsb, randomMsb); assertEquals("Incorrect MSB after loop.", expectedMsb, randomMsb);
try { try {
creator.createGuid(); creator.create();
fail("It should throw an overflow exception."); fail("It should throw an overflow exception.");
} catch (UlidCreatorException e) { } catch (UlidCreatorException e) {
// success // success