This is an automated email from the ASF dual-hosted git repository.
morrySnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 98d55d88c3e [opt](point query) use fastUniqueId instead of
UUID.randomUUID to reduce contention (#63028)
98d55d88c3e is described below
commit 98d55d88c3e3351756e0c8afec44461cf8779a38
Author: HonestManXin <[email protected]>
AuthorDate: Thu May 7 20:46:23 2026 +0800
[opt](point query) use fastUniqueId instead of UUID.randomUUID to reduce
contention (#63028)
```
"mysql-nio-pool-52" #340 daemon prio=5 os_prio=0 tid=0x00007f3ac801d800
nid=0x3e35cd waiting for monitor entry [0x00007f39742d7000]
java.lang.Thread.State: BLOCKED (on object monitor)
at
sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:215)
- waiting to lock <0x00007f3f9c218f58> (a
sun.security.provider.SecureRandom)
at
sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:534)
at
sun.security.provider.NativePRNG$RandomIO.access$400(NativePRNG.java:331)
at
sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:220)
at java.security.SecureRandom.nextBytes(SecureRandom.java:468)
at java.util.UUID.randomUUID(UUID.java:145)
at org.apache.doris.qe.StmtExecutor.execute(StmtExecutor.java:555)
at
org.apache.doris.qe.MysqlConnectProcessor.handleExecute(MysqlConnectProcessor.java:246)
at
org.apache.doris.qe.MysqlConnectProcessor.handleExecute(MysqlConnectProcessor.java:294)
```
In high‑concurrency point‑query scenarios, a large number of requests
require generating a UUID for internal identification. When the request
rate is high, frequent calls to `UUID.randomUUID()` can introduce
contention and become a minor performance bottleneck.
For query, the UUID is only required to provide a unique identifier for
request correlation, and cryptographic strength is not necessary. To
reduce contention and improve throughput, this change introduces
`fastUniqueId`, which generates RFC‑4122 compatible UUID v4 values using
`ThreadLocalRandom`.
By using a per‑thread random generator instead of the shared random
source used by `UUID.randomUUID()`, UUID generation scales better under
high concurrency while still preserving the standard UUID format.
---
.../apache/doris/common/util/UniqueIdUtils.java | 75 ++++++++++++++++++++++
.../java/org/apache/doris/qe/StmtExecutor.java | 16 ++---
.../apache/doris/foundation/util/UUIDUtils.java | 53 +++++++++++++++
3 files changed, 133 insertions(+), 11 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/util/UniqueIdUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/UniqueIdUtils.java
new file mode 100644
index 00000000000..7160dcb6db2
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/UniqueIdUtils.java
@@ -0,0 +1,75 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.common.util;
+
+import org.apache.doris.thrift.TUniqueId;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class UniqueIdUtils {
+
+ private static class Holder {
+ static final SecureRandom numberGenerator = new SecureRandom();
+ }
+
+ /**
+ * Generates a random RFC‑4122 version 4 UUID using {@link
java.util.concurrent.ThreadLocalRandom}.
+ *
+ * <p>This implementation avoids the shared random source used by
+ * {@link java.util.UUID#randomUUID()}, reducing contention in
high‑concurrency
+ * environments and improving throughput.</p>
+ *
+ * <p><b>Trade‑off:</b> {@code ThreadLocalRandom} is not cryptographically
secure.
+ * It should be used for high‑throughput identifiers (e.g. request or
trace IDs),
+ * not for security‑sensitive tokens.</p>
+ */
+ public static TUniqueId fastUniqueId() {
+ final Random ng = ThreadLocalRandom.current();
+ long mostSigBits = ng.nextLong();
+ long leastSigBits = ng.nextLong();
+ // format to uuid v4
+ mostSigBits &= 0xFFFFFFFFFFFF0FFFL;
+ mostSigBits |= 0x0000000000004000L;
+ leastSigBits &= 0x3FFFFFFFFFFFFFFFL;
+ leastSigBits |= 0x8000000000000000L;
+ return new TUniqueId(mostSigBits, leastSigBits);
+ }
+
+ public static TUniqueId randomUniqueId() {
+ // copy from java.util.UUID.randomUUID
+ final SecureRandom ng = Holder.numberGenerator;
+ byte[] data = new byte[16];
+ ng.nextBytes(data);
+ data[6] &= 0x0f; /* clear version */
+ data[6] |= 0x40; /* set to version 4 */
+ data[8] &= 0x3f; /* clear variant */
+ data[8] |= 0x80; /* set to IETF variant */
+ long msb = 0;
+ long lsb = 0;
+ for (int i = 0; i < 8; i++) {
+ msb = (msb << 8) | (data[i] & 0xff);
+ }
+ for (int i = 8; i < 16; i++) {
+ lsb = (lsb << 8) | (data[i] & 0xff);
+ }
+ return new TUniqueId(msb, lsb);
+ }
+
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index c5dc61d15f5..11d633a5644 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -62,6 +62,7 @@ import org.apache.doris.common.util.DebugPointUtil.DebugPoint;
import org.apache.doris.common.util.DebugUtil;
import org.apache.doris.common.util.NetUtils;
import org.apache.doris.common.util.TimeUtils;
+import org.apache.doris.common.util.UniqueIdUtils;
import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.FileScanNode;
import org.apache.doris.datasource.tvf.source.TVFScanNode;
@@ -166,7 +167,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
@@ -561,8 +561,7 @@ public class StmtExecutor {
// query with a random sql
public void execute() throws Exception {
- UUID uuid = UUID.randomUUID();
- TUniqueId queryId = new TUniqueId(uuid.getMostSignificantBits(),
uuid.getLeastSignificantBits());
+ TUniqueId queryId = UniqueIdUtils.fastUniqueId();
if (Config.enable_print_request_before_execution) {
LOG.info("begin to execute query {} {}",
DebugUtil.printId(queryId), originStmt == null ? "null" :
originStmt.originStmt);
@@ -572,7 +571,6 @@ public class StmtExecutor {
public void queryRetry(TUniqueId queryId) throws Exception {
TUniqueId firstQueryId = queryId;
- UUID uuid;
int retryTime = Config.max_query_retry_time;
retryTime = retryTime <= 0 ? 1 : retryTime + 1;
// If the query is an `outfile` statement,
@@ -595,8 +593,7 @@ public class StmtExecutor {
throw e;
}
TUniqueId lastQueryId = queryId;
- uuid = UUID.randomUUID();
- queryId = new TUniqueId(uuid.getMostSignificantBits(),
uuid.getLeastSignificantBits());
+ queryId = UniqueIdUtils.fastUniqueId();
int randomMillis = 10 + (int) (Math.random() * 10);
if (i > retryTime / 2) {
randomMillis = 20 + (int) (Math.random() * 10);
@@ -971,9 +968,7 @@ public class StmtExecutor {
try {
// reset query id for each retry
if (i > 0) {
- UUID uuid = UUID.randomUUID();
- TUniqueId newQueryId = new
TUniqueId(uuid.getMostSignificantBits(),
- uuid.getLeastSignificantBits());
+ TUniqueId newQueryId = UniqueIdUtils.fastUniqueId();
AuditLog.getQueryAudit().log("Query {} {} times with new
query id: {}",
DebugUtil.printId(queryId), i,
DebugUtil.printId(newQueryId));
context.setQueryId(newQueryId);
@@ -2022,8 +2017,7 @@ public class StmtExecutor {
if (LOG.isDebugEnabled()) {
LOG.debug("INTERNAL QUERY: {}", originStmt.toString());
}
- UUID uuid = UUID.randomUUID();
- TUniqueId queryId = new TUniqueId(uuid.getMostSignificantBits(),
uuid.getLeastSignificantBits());
+ TUniqueId queryId = UniqueIdUtils.fastUniqueId();
context.setQueryId(queryId);
if (originStmt.originStmt != null) {
context.setSqlHash(DigestUtils.md5Hex(originStmt.originStmt));
diff --git
a/fe/fe-foundation/src/main/java/org/apache/doris/foundation/util/UUIDUtils.java
b/fe/fe-foundation/src/main/java/org/apache/doris/foundation/util/UUIDUtils.java
new file mode 100644
index 00000000000..0feff359ebc
--- /dev/null
+++
b/fe/fe-foundation/src/main/java/org/apache/doris/foundation/util/UUIDUtils.java
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.foundation.util;
+
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class UUIDUtils {
+
+ /**
+ * Generates a random RFC‑4122 version 4 UUID using {@link
java.util.concurrent.ThreadLocalRandom}.
+ *
+ * <p>This implementation avoids the shared random source used by
+ * {@link java.util.UUID#randomUUID()}, reducing contention in
high‑concurrency
+ * environments and improving throughput.</p>
+ *
+ * <p><b>Trade‑off:</b> {@code ThreadLocalRandom} is not cryptographically
secure.
+ * It should be used for high‑throughput identifiers (e.g. request or
trace IDs),
+ * not for security‑sensitive tokens.</p>
+ */
+ public static UUID fastUUID() {
+ final Random ng = ThreadLocalRandom.current();
+ long mostSigBits = ng.nextLong();
+ long leastSigBits = ng.nextLong();
+ // format to uuid v4
+ mostSigBits &= 0xFFFFFFFFFFFF0FFFL;
+ mostSigBits |= 0x0000000000004000L;
+ leastSigBits &= 0x3FFFFFFFFFFFFFFFL;
+ leastSigBits |= 0x8000000000000000L;
+
+ return new UUID(mostSigBits, leastSigBits);
+ }
+
+ public static UUID randomUUID() {
+ return UUID.randomUUID();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]