I have a web based Java application that generates random UUIDs for session information. One of our testers is claiming up to 350ms to generate UUIDs based upon his own profiling, but I have not yet been able to replicate his results. He points to this article http://www.cowtowncoder.com/blog/archives/2010/10/entry_429.html to help back up his results. I wanted to see if anyone else has ran into this limitation with Java's built-in UUID generation capability in either Java 6 or Java 7 applications.
-
350ms to generate *one* UUID? How is he backing that up with the article you are linking to? – jarnbjo Jan 26 '13 at 01:52
-
It is the profiling tool he is using. I haven't been able to replicate on my end yet. That is why I wanted to check to see if there is a similar problem anyone else has experienced. It could be an issue with a profiling tool or maybe it be an odd combination of Java with runtime environment. It seemed odd to me as well. – Shawn H Jan 26 '13 at 02:14
-
Once again: Does he claim that it takes 350ms to generate *one* UUID (as you write UUIDs in plural, without actually specifying how many)? How is he backing that up with the article you are linking to? There is nothing in that article suggesting that the UUID generator is so slow. Another question: Which OS is the tester running it's test on? Java on Linux uses the /dev/urandom generator, which can be rather slow if there is not much activity (e.g. user input or network traffic) on that system. – jarnbjo Jan 26 '13 at 02:23
-
The claim was 350ms to generate a single UUID. Our default systems are Macbook Pros running Mountain Lion. Production systems are the latest version of CentOS. – Shawn H Jan 26 '13 at 02:30
-
350ms? I made [one](http://pastebin.com/SZkZp1bk) in C that generates 400,000 UUIDs a second on a newer macbook pro. But that's not really a fair comparison ;) – Jerfov2 Jul 10 '15 at 23:25
-
@Jerfov2 not "cryptographically secure"? https://crypto.stackexchange.com/a/3525/74491 – rogerdpack Nov 23 '19 at 18:38
7 Answers
Here is a test run in beta 127.
Keep in mind that this test is unrealistic, beyond any worst-case scenario I can imagine. My goal was to quiet those who bad-mouth use of UUIDs without the facts to back up their criticism.
Scenario:
- A tight loop of a million calls to
java.util.UUID.randomUUID()
- One test with just that alone. (no contention)
- One test with contention, where 2 other threads are in a tight loop making ten million calls.
- Java 8 beta 127
- java version "1.8.0"
- Java(TM) SE Runtime Environment (build 1.8.0-b127)
- Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)
- Run from Netbeans 7.4 IDE
- Executing inside a virtual machine
- Parallels 9 virtual machine
- Mountain Lion
- 3 virtual cores
- 4 gigs memory
- Mac mini (late 2012)
Without Contention
Running one loop in one thread, so no contention over the synchronized methods/classes.
// Warm the random generator.
java.util.UUID uuid;
uuid = java.util.UUID.randomUUID();
long stop = 0;
long start = System.nanoTime();
int loops = 1000000; // One million.
for ( int i = 0; i < loops; i++ ) {
uuid = java.util.UUID.randomUUID();
}
stop = System.nanoTime();
long elapsed = ( stop - start );
System.out.println( "UUIDs: " + loops );
System.out.println( "Nanos: " + elapsed );
System.out.println( "Nanos per uuid: " + ( elapsed / loops ) + " ( micros per: " + ( elapsed / loops / 1000 ) + " )" );
Results
About 2 microseconds per UUID.
With Contention
Similar to above, but while doing a loop of a million calls, we have two other threads running where each makes ten million calls.
// Warm the random generator.
java.util.UUID uuid;
uuid = java.util.UUID.randomUUID();
int pass = 10_000_000 ; // Ten million.
MyThread t1 = new MyThread( pass );
MyThread t2 = new MyThread( pass );
t1.start();
t2.start();
t3.start();
long stop = 0;
long start = System.nanoTime();
int loops = 1_000_000 ; // One million.
for ( int i = 0; i < loops; i++ ) {
uuid = java.util.UUID.randomUUID();
}
stop = System.nanoTime();
long elapsed = ( stop - start );
System.out.println( "UUIDs: " + loops );
System.out.println( "Nanos: " + elapsed );
System.out.println( "Nanos per uuid: " + ( elapsed / loops ) + " ( micros per: " + ( elapsed / loops / 1000 ) + " )" );
And the class defining each thread…
class MyThread extends Thread {
private int loops;
public MyThread( int loops ) {
this.loops = loops;
}
@Override
public void run() {
java.util.UUID uuid;
for ( int i = 0; i < this.loops; i++ ) {
uuid = java.util.UUID.randomUUID();
}
}
}
Results
About 20 microseconds per UUID.
Runs were 14, 20, 20, 23, and 24 microseconds per UUID (not in that order). So under extreme contention was only about 10 times worse, with 20 microseconds being acceptable in any real-world usage I've known.

- 303,325
- 100
- 852
- 1,154
-
5uhh, correct me if I'm wrong, but your math is `nanos / 1000`, which is _micro_ seconds, **not** _milli_ seconds. – Groostav Sep 29 '16 at 05:32
-
3Are you using the variable uuid anywhere? If you don't use it you might be testing nothing as the JVM optimizes the code when it detects that a variable is not used. Have a look at Java Performance by Scott Oaks. You might need to declare a volatile field to be sure the benchmark is measuring anything useful. – Jorge Viana Nov 16 '19 at 11:06
-
There is no f..in way it takes 20 microseconds to generate true random UUID period, let alone in contended environment. – vach Jan 11 '22 at 10:36
The random form of UUID typically uses a source of "cryptography strength" random numbers.
(If it didn't then so-called random UUIDs would be predictable, and the probability that a given UUID is reissued could increase to worrying levels. As another answer suggests, you could provide a fast (but weak) PRNG to the UUID
constructor. But that would be a bad idea.)
Typical crypto-strength random number generators use a source of entropy that is external to the application. It might be a hardware random number generator, but more commonly it is accumulated "randomness" that is harvested by the operating system in normal operation. The problem is that sources of entropy have a rate limit. If you exceed that rate over a period of time, you can drain the source. What happens next is system dependent, but on some systems the syscall to read entropy will stall ... until more is available.
I expect that is what is happening on your client's system. (It is not uncommon on virtual machines ...)
One hacky work-around (for Linux systems) is to install the rngd
daemon and configure it to "top up" the entropy pool using a good pseudo-random number generator. A security expert would point that:
- this will affect your UUID generator's randomness, and
- the entropy pool is used for other security-related things, so topping it up from a dubious source is weakening security for many things on your system.
I'm not sure how safe this hack would be in practice.
Here's another Q&A on the topic of slow random number generation:

- 698,415
- 94
- 811
- 1,216
-
2I think we have run into the "lack of entropy" problem as well. The UUID generation starts out fast but after a few hours can come to a crawl. Running on a headless VM may be contributing to the problem as the OS has less sources of entropy. See http://stackoverflow.com/questions/137212/how-to-solve-performance-problem-with-java-securerandom for more info. – Dr. Mike Hopper Sep 18 '13 at 09:08
-
The answer from user Basil Bourque includes a benchmark demonstrating 20 us per UUID on average during a benchmark with 3 threads in contention each generating UUIDs as fast as possible. Do you think this entropy rate limit would affect such a benchmark if it were run for a long period of time, where the average us per UUID would be greater for test runs for longer periods of time? – Matt Welke Sep 10 '21 at 18:57
-
I tested it
for (;;) {
long t0 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
UUID.randomUUID();
}
System.out.println(System.currentTimeMillis() - t0);
}
on my PC it is ~1100 ms, which is pretty slow. UUID.randomUUID() uses SecureRandom internally, to make it faster we can use regular java.util.Random
Random r = new Random();
for (;;) {
..
new UUID(r.nextLong(), r.nextLong());
it's ~80 ms

- 133,369
- 30
- 199
- 275
-
4Those numbers don't pass the smell test. 1110ms to generate 1 million random UUIDs sounds way fast. But 1110ms to generat 1 UUID sounds way too slow. – Stephen C Jan 26 '13 at 07:36
-
1By me the speed of both methods is similar, but it's the Windows machine. – Danubian Sailor Jan 26 '13 at 18:37
-
14It uses SecureRandom for a reason, you should not "use regular java.util.Random", and not expect UUID clashes. – Mikkel Løkke Apr 28 '14 at 13:08
-
3@MikkelLøkke I'm not sure your reasoning is correct. I think the big issue is predictability, _not_ uniformity. UUID's might be used for secure purposes --as an unguessable key--, which requires high quality entropy. But in many cases, where the goal is an insecure avoidance of collision, I believe the `random.nextLong()` strategy will suffice. – Groostav Sep 29 '16 at 05:42
-
I'm not sure what you mean by predictability or uniformity. A type 4 UUID is essentially a 122 bit pseudo random number generator, like all other pseudo random number generators, the risk of generating the same number (clashes) largely depends on entropy. Also UUID's shouldn't be used as unguessable keys (because they are trivially bruteforced) they should be used as Universally Unique IDentifiers, and the more of them you generate the higher the probability of clashes. Particularly if you're using something like libc.rand for entropy. – Mikkel Løkke Sep 29 '16 at 12:14
-
1@MikkelLøkke How are uuid's "trivially bruteforced"? Consider 1 billion a second for 30 years straight is about 2^60, which is less than the square root of the uuid-space but many many orders of magnitude more than can be expected to be generated perhaps by the entire planet in that time, but certainly in a single application. Could you elaborate on how you feel type 4 uuids are trivially bruteforced? – corsiKa Dec 30 '18 at 08:44
-
@corsiKa I think you are vastly overestimating the entropy og the java.util.Random, generator if you think the search space is more than 2^60. – Mikkel Løkke Jan 14 '19 at 14:55
-
@MikkelLøkke UUID uses [SecureRandom](https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html) which is cryptographically strong, but okay. – corsiKa Jan 14 '19 at 16:26
-
1@corsiKa Yeah but this answer is *specifically* about improving performance, by using `java.util.Random` instead, which in my opinion is a terrible idea, unless you fully understand the consequences, which was what I was elaboraing on when I said that they could be trivially bruteforced. – Mikkel Løkke Jan 15 '19 at 15:17
-
1Oh I see what you're saying. It's not that UUID is trivially brute forced. It's that `java.util.Random` is trivially brute forced. Absolutely, I forget if it's 2 or 3 calls is all that's necessary to predict all future calls. I think Groostav's point about uniformity holds logically, that is to say there isn't a practical attack vector for someone generating uuid collisions in your app if you use `java.util.Random` but you're right that a theoretical one does exist - and when it is literally SOOO cheap (c'mon people, 50k uuids a second is fine!) why not just eliminate the vector altogether. – corsiKa Jan 15 '19 at 21:29
The number of threads has a huge impact on the performance of the generation of UUIDs. This can be explained by looking at the implementation of SecureRandom#nextBytes(byte[]
which generates the random numbers for UUID.randomUUID()
:
synchronized public void nextBytes(byte[] bytes) {
secureRandomSpi.engineNextBytes(bytes);
}
nextBytes
is synchronized
which leads to significant performance loss when accessed by different threads.

- 7,526
- 2
- 26
- 29
Use Version 1 Instead of 4
How about using Version 1 type of UUID?
Version 1 is based on MAC address and current time ("space and time"). Much less likely to have collisions than Version 4.
Version 4 is based on entirely being generated from random numbers using a cryptographically strong random generator.
The Oracle JVM does not provide a Version 1 generator, apparently because of security and privacy concerns. The JVM does not provide access to the MAC address of host machine.
JUG Library
There is at least one third-party library available that doe provide Version 1 UUIDs, as well as other versions: JUG – Java UUID Generator. They say features introduced in Java 6 let them get access to the MAC address.
Test Results: 20x
Read a discussion of performance with test results using Java UUID Generator version 3 in the 2010 article, More on Java UUID Generator (JUG), a word on performance. Tatu Saloranta tested various kinds of UUIDs on his MacBook.
Upshot: MAC+Time version is 20 times faster that random version.
Time-based variant (Ethernet address plus timestamp) is much faster -- almost 20 times as fast as Random-based default variant -- generating about 5 million UUIDs per second.

- 303,325
- 100
- 852
- 1,154
A junit test run under jdk 1.7.0_40:
package org.corba.util;
import org.junit.Test;
import org.springframework.util.StopWatch;
import java.util.UUID;
/**
* Test of performance of Java's UUID generation
* @author Corba Da Geek
* Date: 1/6/14
* Time: 3:48 PM
*/
public class TestRandomUUID {
private static final int ITERATIONS = 1000000;
@Test
public void testRandomUUID() throws Exception {
// Set up data
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// Run test
for (int i = 0; i < ITERATIONS; i++)
UUID.randomUUID();
// Check results
stopWatch.stop();
final long totalTimeMillis = stopWatch.getTotalTimeMillis();
System.out.println("Number of milliseconds: " + totalTimeMillis + " for " + ITERATIONS + " iterations.");
System.out.println(String.format("Average time per iteration: %.7f ms", (float)totalTimeMillis/ITERATIONS));
}
}
And the results on my i5 laptop were:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.corba.util.TestRandomUUID
Number of milliseconds: 677 for 1000000 iterations.
Average time per iteration: 0.0006770 ms
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.746 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
0.0006770 ms per invocation.

- 71
- 1
- 4
-
4Are you sure that JVM didn't remove `UUID.randomUUID();` line as its results isn't used? – Dariusz Mydlarz Apr 21 '16 at 08:32
I did the same test as the others and my results are more like 300 NANOseconds per UUID generation. Results are on a i7 quad-core WIN7 64 PC. I tried with a jdk1.7.0_67 and with a jdk1.8.0_40 64 bits JVMs.
I'm kind of perplex my results are so different than all others... But 1 ms for generating a random number seemed a LOT !
public static void main(String[] args) throws Exception {
long start = System.nanoTime();
int loops = 1000000; // One million.
long foo = 0;
for (int i = 0; i < loops; i++) {
UUID uuid = java.util.UUID.randomUUID();
//this is just to make sure there isn't some kind of optimization
//that would prevent the actual generation
foo += (uuid.getLeastSignificantBits()
+ uuid.getMostSignificantBits());
}
long stop = System.nanoTime();
long elapsed = (stop - start);
System.out.println(String.format("UUIDs : %,d", loops));
System.out.println(String.format("Total time (ns) : %,d", elapsed));
System.out.println(String.format("Time per UUID (ns) : %,d", (elapsed / loops)));
System.out.println();
System.out.println(foo);
}
The output :
UUIDs : 1 000 000
Total time (ns) : 320 715 288
Time per UUID (ns) : 320
5372630452959404665

- 10,171
- 2
- 19
- 27