MeasurePerformance.java
package perf;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
import com.fasterxml.uuid.*;
import com.fasterxml.uuid.impl.RandomBasedGenerator;
import com.fasterxml.uuid.impl.TimeBasedGenerator;
/**
* Simple micro-benchmark for evaluating performance of various UUID generation
* techniques, including JDK's method as well as JUG's versions.
*<p>
* Notes: for name-based version we will pass plain Strings, assuming this is the
* most common use case; even though it is possible to also pass raw byte arrays.
* JDK and Jug implementations have similar performance so this only changes
* relative speeds of name- vs time-based versions.
*
* @since 3.1
*/
public class MeasurePerformance
{
// also: let's just use a single name for name-based, to avoid extra overhead:
private final static String NAME_STRING = "http://www.cowtowncoder.com/blog/blog.html";
private final static byte[] NAME_BYTES = NAME_STRING.getBytes(StandardCharsets.UTF_8);
// Let's generate 50k UUIDs per test round
private static final int COUNT = 1000;
private static final int DEFAULT_ROUNDS = 50;
private final int rounds;
private final boolean runForever;
public MeasurePerformance() { this(DEFAULT_ROUNDS, true); }
public MeasurePerformance(int rounds, boolean runForever) {
this.rounds = rounds;
this.runForever = runForever;
}
public void test() throws Exception
{
int i = 0;
final Object[] uuids = new Object[COUNT];
// can either use bogus address; or local one, no difference perf-wise
EthernetAddress nic = EthernetAddress.fromInterface();
// Whether to include namespace? Depends on whether we compare with JDK (which does not)
// UUID namespaceForNamed = NAMESPACE;
UUID namespaceForNamed = null;
final RandomBasedGenerator secureRandomGen = Generators.randomBasedGenerator();
final RandomBasedGenerator utilRandomGen = Generators.randomBasedGenerator(new java.util.Random(123));
final TimeBasedGenerator timeGenPlain = Generators.timeBasedGenerator(nic);
final TimeBasedGenerator timeGenSynced = Generators.timeBasedGenerator(nic,
new com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer());
final StringArgGenerator nameGen = Generators.nameBasedGenerator(namespaceForNamed);
boolean running = true;
final long sleepTime = runForever ? 350L : 1L;
while (running) {
Thread.sleep(sleepTime);
int round = (i++ % 7);
long curr = System.currentTimeMillis();
String msg;
boolean lf = (round == 0);
switch (round) {
case 0:
msg = "JDK, random";
testJDK(uuids, rounds);
break;
case 1:
msg = "JDK, name";
testJDKNames(uuids, rounds);
break;
case 2:
msg = "Jug, time-based (non-sync)";
testTimeBased(uuids, rounds, timeGenPlain);
break;
case 3:
msg = "Jug, time-based (SYNC)";
testTimeBased(uuids, rounds, timeGenSynced);
break;
case 4:
msg = "Jug, SecureRandom";
testRandom(uuids, rounds, secureRandomGen);
break;
case 5:
msg = "Jug, java.util.Random";
testRandom(uuids, rounds, utilRandomGen);
break;
case 6:
msg = "Jug, name-based";
testNameBased(uuids, rounds, nameGen);
// Last one, quit unless running forever
if (!runForever) {
running = false;
}
break;
/*
case 7:
msg = "http://johannburkard.de/software/uuid/";
testUUID32(uuids, rounds);
break;
*/
default:
throw new Error("Internal error");
}
curr = System.currentTimeMillis() - curr;
if (lf) {
System.out.println();
}
System.out.println("Test '"+msg+"' -> "+curr+" msecs; last UUID: "+uuids[COUNT-1]);
}
}
// Test implementation from http://johannburkard.de/software/uuid/
/*
private final void testUUID32(Object[] uuids, int rounds)
{
while (--rounds >= 0) {
for (int i = 0, len = uuids.length; i < len; ++i) {
uuids[i] = new com.eaio.uuid.UUID();
}
}
}
*/
private final void testJDK(Object[] uuids, int rounds)
{
while (--rounds >= 0) {
for (int i = 0, len = uuids.length; i < len; ++i) {
uuids[i] = UUID.randomUUID();
}
}
}
private final void testJDKNames(Object[] uuids, int rounds) throws java.io.IOException
{
while (--rounds >= 0) {
for (int i = 0, len = uuids.length; i < len; ++i) {
final byte[] nameBytes = NAME_BYTES;
uuids[i] = UUID.nameUUIDFromBytes(nameBytes);
}
}
}
private final void testRandom(Object[] uuids, int rounds, RandomBasedGenerator uuidGen)
{
while (--rounds >= 0) {
for (int i = 0, len = uuids.length; i < len; ++i) {
uuids[i] = uuidGen.generate();
}
}
}
private final void testTimeBased(Object[] uuids, int rounds, TimeBasedGenerator uuidGen)
{
while (--rounds >= 0) {
for (int i = 0, len = uuids.length; i < len; ++i) {
uuids[i] = uuidGen.generate();
}
}
}
private final void testNameBased(Object[] uuids, int rounds, StringArgGenerator uuidGen)
{
while (--rounds >= 0) {
for (int i = 0, len = uuids.length; i < len; ++i) {
uuids[i] = uuidGen.generate(NAME_STRING);
}
}
}
public static void main(String[] args) throws Exception
{
new MeasurePerformance(DEFAULT_ROUNDS, true).test();
}
}