在 Java 中,我们常用 UUID.randomUUID()
来随机生成一个 UUID。但在某些极端的情况下,它的性能可能满足不了你的要求(虽然几乎不可能出现)。这里我们测试了 4 种 UUID 生成器的性能。
最终测试的结果如下(虽然只看到 3 根线,但其实有 4 根,其中蓝线 UUID.randomUUID 与绿线 jugWithSecureRandom 几乎重合):
可以看到:
synchronized
randomUUID
。 这里我们测试了 java 内置的 UUID.randomUUID()
, java-uuid-generator 的 TimeBasedGenerator
和 RandomBasedGenerator
,而其中随机数发生器分别选用 Random
和 SecureRandom
。 测试代码 如下:
@BenchmarkMode({Mode.Throughput}) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @Warmup(iterations = 5) public class MyBenchmark { private RandomBasedGenerator randomBasedGenerator; private RandomBasedGenerator jugRandomGenerator; private TimeBasedGenerator timeBasedGenerator; @Setup public void init() { randomBasedGenerator = Generators.randomBasedGenerator(); timeBasedGenerator = Generators.timeBasedGenerator(); jugRandomGenerator = Generators.randomBasedGenerator(new Random()); } @Benchmark public void UUIDRandomUUID(Blackhole bh) { bh.consume(UUID.randomUUID()); } @Benchmark public void jugWithRandom(Blackhole bh) { bh.consume(jugRandomGenerator.generate()); } @Benchmark public void jugWithSecureRandom(Blackhole bh) { bh.consume(randomBasedGenerator.generate()); } @Benchmark public void jugTime(Blackhole bh) { bh.consume(timeBasedGenerator.generate()); } }
测试框架使用 Jmh。测试使用 jdk 1.8 在 8C MacBook Pro 下完成,分别测试了 1,2,4,8
个线程下的吞吐。
这个测试的起因是产品在压测的时候发现 UUID 生成占 Running 线程较大的部分,且 JProfiler 的线程图中有许多线程是 Blocking 的状态,因此猜测是 UUID.randomUUID中的synchronized 导致线程同步慢,所以想找一些替代的生成器。最后发现 UUID.randomUUID 的吞吐并不是什么大的问题,但也很庆幸做了这个测试,了解了 UUID 生成器的能力,还有 Time-Based UUID 也是一个不错的选择。