Which GUID Generation Method Wins? Performance Test of UUID, Snowflake, ThreadLocal & Atomic
An extensive performance benchmark compares four GUID generation techniques—UUID, Snowflake algorithm, ThreadLocal exclusive counters, and atomic counters—across varying thread counts, revealing that ThreadLocal excels in high‑concurrency single‑machine scenarios while Snowflake remains stable for distributed use, with detailed optimization recommendations.
In the Supermarket Eight tracking system, generating a globally unique identifier (GUID) is critical for log tracing and database indexing efficiency. This section quantifies the performance of four schemes—UUID, Snowflake algorithm, ThreadLocal exclusive counters, and atomic counters—through throughput tests under different concurrency levels, excluding centralized services due to network latency.
11.4.2.1 Tool Class Design
To simplify test cases and improve code readability, a UniqueUtils utility class is designed to encapsulate the four unique‑ID generation methods. The class code is shown below:
package org.funtester.performance.books.chapter11.section4;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
/**
* Global unique identifier utility class, providing UUID, Snowflake algorithm,
* thread‑exclusive and atomic operations.
*/
public class UniqueUtils {
private static final SnowflakeWorker SNOW_WORKER; // Snowflake object
private static final long ORIGIN = 1000000000000000000L; // start value
private static final ThreadLocal<Long> EXCLUSIVE = ThreadLocal.withInitial(() -> 0L); // lock‑free counter
private static final AtomicLong ATOMIC = new AtomicLong(0); // atomic counter
static {
SNOW_WORKER = new SnowflakeWorker(1, 1); // data center ID=1, machine ID=1
}
/** Get Snowflake unique identifier */
public static String getSnowMark() {
return String.valueOf(SNOW_WORKER.nextId());
}
/** Get UUID unique identifier */
public static String getUUID() {
return UUID.randomUUID().toString();
}
/** Get thread‑exclusive unique identifier */
public static String getExclusiveMark() {
Long id = EXCLUSIVE.get();
EXCLUSIVE.set(id + 1);
return String.valueOf(id + ORIGIN);
}
/** Get atomic unique identifier */
public static String getAtomicMark() {
return String.valueOf(ATOMIC.getAndIncrement() + ORIGIN);
}
}Snowflake Algorithm Optimization
To address possible clock‑rollback issues in high‑concurrency scenarios, the SnowflakeWorker.nextId() method is enhanced with fault‑tolerant logic:
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
if (lastTimestamp - timestamp >= 2000L) {
throw new RuntimeException("Clock moved backwards more than 2 seconds, refusing to generate ID, time difference " + (lastTimestamp - timestamp) + " ms");
} else {
timestamp = lastTimestamp; // use last timestamp
}
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
if (sequence == 0) {
timestamp = nextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
long id = ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) |
(dataId << DATA_CENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
return id & Long.MAX_VALUE;
}If the rollback is less than 2 seconds, the previous timestamp is reused to avoid interruption; otherwise an exception is thrown to signal a clock problem.
11.4.2.2 Test Results and Analysis
Throughput (ops/μs) was measured for 1, 10, 40, and 100 threads. Summary tables:
Method
Score (ops/μs)
atomic
78.779
exclusive
72.593
uuid
11.706
snow
4.096
Method
Score (ops/μs)
exclusive
248.632
atomic
18.964
uuid
4.639
snow
4.095
Method
Score (ops/μs)
exclusive
353.736
atomic
19.621
uuid
3.989
snow
4.096
Method
Score (ops/μs)
exclusive
374.932
atomic
19.993
uuid
4.661
snow
4.096
ThreadLocal (exclusive) : Best performance in high‑concurrency (10, 40, 100 threads), scaling from 72.593 ops/μs (1 thread) to 374.932 ops/μs (100 threads) due to lock‑free ThreadLocal operations.
Atomic : Highest single‑thread throughput (78.779 ops/μs) but degrades under contention, falling to ~20 ops/μs at 100 threads.
UUID : Lowest throughput (≈4–5 ops/μs) because of string generation and random computation overhead; suitable for non‑performance‑critical logging.
Snowflake : Stable but lowest performance (≈4 ops/μs) limited by synchronized locking and bit‑wise calculations; fits distributed scenarios but not single‑machine high‑concurrency.
Concurrency Trend : Lock‑free solutions (exclusive) dominate as threads increase, while atomic suffers CAS contention and UUID/Snowflake remain comparatively low.
Supermarket Eight Application
Single‑machine high concurrency : Prefer ThreadLocal (exclusive) for request IDs, balancing throughput and thread isolation.
Distributed scenario : Use the optimized Snowflake to generate order IDs across multiple nodes.
Log tracing : Employ UUID for readable IDs that aid debugging.
Atomic fallback : AtomicInteger is a secondary choice for simple incremental IDs in moderate concurrency.
11.4.3.3 Optimization Recommendations
For single‑machine tracking, prioritize ThreadLocal combined with FunObjPool reuse of UserBehavior objects to reduce allocation.
Deploy the optimized Snowflake with proper data‑center and machine IDs and monitor clock synchronization.
Validate ThreadLocal stability at higher thread counts (e.g., 200 threads).
Adjust ORIGIN in UniqueUtils to shorten ID length for exclusive and atomic schemes, saving storage.
After code or JDK upgrades, re‑run performance tests to ensure no new bottlenecks.
11.4.3 Summary
This section compared the performance of UUID, Snowflake, ThreadLocal, and atomic unique‑ID generators, highlighting the superiority of ThreadLocal in single‑machine high‑concurrency environments and the suitability of Snowflake for distributed use. The Supermarket Eight team should adopt ThreadLocal for tracking IDs and integrate Snowflake for order IDs, while continuously monitoring and optimizing the implementations to support millions of users with stable, efficient identifier generation.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
