This is an automated email from the ASF dual-hosted git repository.

zhaojinchao95 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 58958c5e1b1 Add pre get to avoid ConcurrentHashMap#computeIfAbsent 
performance problem in JDK 8 (#38707)
58958c5e1b1 is described below

commit 58958c5e1b1e677c70c2f5280f3c342703c1e43a
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Wed May 20 18:43:45 2026 +0800

    Add pre get to avoid ConcurrentHashMap#computeIfAbsent performance problem 
in JDK 8 (#38707)
---
 .codex/skills/review-pr/SKILL.md                               |  7 ++++++-
 .../transaction/savepoint/ConnectionSavepointManager.java      | 10 +++++++++-
 .../postgresql/command/PostgreSQLPortalContextRegistry.java    |  6 +++++-
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/.codex/skills/review-pr/SKILL.md b/.codex/skills/review-pr/SKILL.md
index c4863ea4be9..c28f62c3aa3 100644
--- a/.codex/skills/review-pr/SKILL.md
+++ b/.codex/skills/review-pr/SKILL.md
@@ -67,6 +67,9 @@ description: >-
     - If official documentation support is missing, ambiguous, or contradicts 
the PR behavior, bias to `Merge Verdict: Not Mergeable`.
     - If any related dialect remains unresolved, or the review skips the 
family scan, bias to `Merge Verdict: Not Mergeable`.
     - Do not recommend unsupported or undocumented SQL syntax in review 
feedback.
+16. If a method reachable from the Proxy or JDBC DML/DQL high-frequency SQL 
execution path uses `ConcurrentHashMap#computeIfAbsent`,
+    require a preceding `get` lookup and call `computeIfAbsent` only when the 
value is missing, to avoid the JDK 8 implementation bottleneck.
+    If this pattern is absent and the path is high-frequency, bias to `Merge 
Verdict: Not Mergeable`.
 
 ## Execution Boundary
 
@@ -142,6 +145,7 @@ When information gaps block mergeability, request at least:
 4. Risk scan:
    - Design: abstraction level, responsibility boundaries, temporary 
compatibility branches
    - Performance: new loops/remote calls/object allocations on hot paths
+   - Performance: in Proxy/JDBC DML/DQL high-frequency SQL paths, flag direct 
`ConcurrentHashMap#computeIfAbsent` use without a preceding `get` miss check
    - Compatibility: behavior/config/API-SPI/SQL dialect versions
    - Regression: similar statements, adjacent features, exception branches
    - For parser, binder, routing, and default-schema changes, explicitly 
compare the new behavior against official dialect semantics and check whether 
precedence or shadowing rules changed
@@ -189,7 +193,7 @@ If the root-cause chain cannot be fully proven fixed, set 
`Merge Verdict: Not Me
 ## Risk Checklist (Must Cover)
 
 - Design risk: broken layering, duplicated logic, bypassed SPI/metadata cache, 
implicit state.
-- Performance risk: complexity increase, extra hot-path allocations, unbounded 
retries, blocking I/O.
+- Performance risk: complexity increase, extra hot-path allocations, unbounded 
retries, blocking I/O, or direct `ConcurrentHashMap#computeIfAbsent` in 
Proxy/JDBC DML/DQL high-frequency SQL paths without a preceding `get` miss 
check.
 - Compatibility risk:
   - Behavior compatibility
   - Config compatibility
@@ -286,3 +290,4 @@ Use committer tone, gentle wording, no emojis; structure:
 - Do not include emojis in change request text.
 - Do not output `Mergeable` for a shared-code change unless you have checked 
at least one non-target dialect or feature that also uses the changed path.
 - Do not output `Mergeable` when local verification omitted `-am` on a 
module-scoped Maven run and dependency freshness matters.
+- Do not output `Mergeable` when Proxy/JDBC DML/DQL high-frequency SQL paths 
directly call `ConcurrentHashMap#computeIfAbsent` without a preceding `get` 
miss check.
diff --git 
a/kernel/transaction/core/src/main/java/org/apache/shardingsphere/transaction/savepoint/ConnectionSavepointManager.java
 
b/kernel/transaction/core/src/main/java/org/apache/shardingsphere/transaction/savepoint/ConnectionSavepointManager.java
index fba6ffca153..b705dc80278 100644
--- 
a/kernel/transaction/core/src/main/java/org/apache/shardingsphere/transaction/savepoint/ConnectionSavepointManager.java
+++ 
b/kernel/transaction/core/src/main/java/org/apache/shardingsphere/transaction/savepoint/ConnectionSavepointManager.java
@@ -60,7 +60,15 @@ public final class ConnectionSavepointManager {
      */
     public void setSavepoint(final Connection connection, final String 
savepointName) throws SQLException {
         Savepoint result = connection.setSavepoint(savepointName);
-        CONNECTION_SAVEPOINT_MAP.computeIfAbsent(connection, unused -> new 
LinkedHashMap<>()).put(savepointName, result);
+        getConnectionSavepoints(connection).put(savepointName, result);
+    }
+    
+    private Map<String, Savepoint> getConnectionSavepoints(final Connection 
connection) {
+        Map<String, Savepoint> result = 
CONNECTION_SAVEPOINT_MAP.get(connection);
+        if (null == result) {
+            result = CONNECTION_SAVEPOINT_MAP.computeIfAbsent(connection, 
unused -> new LinkedHashMap<>());
+        }
+        return result;
     }
     
     /**
diff --git 
a/proxy/frontend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/PostgreSQLPortalContextRegistry.java
 
b/proxy/frontend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/PostgreSQLPortalContextRegistry.java
index d57ffdd25ca..d4e3bda5caa 100644
--- 
a/proxy/frontend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/PostgreSQLPortalContextRegistry.java
+++ 
b/proxy/frontend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/command/PostgreSQLPortalContextRegistry.java
@@ -49,7 +49,11 @@ public final class PostgreSQLPortalContextRegistry {
      * @return PostgreSQL portal context
      */
     public PortalContext get(final int connectionId) {
-        return portalContexts.computeIfAbsent(connectionId, unused -> new 
PortalContext());
+        PortalContext result = portalContexts.get(connectionId);
+        if (null == result) {
+            result = portalContexts.computeIfAbsent(connectionId, unused -> 
new PortalContext());
+        }
+        return result;
     }
     
     /**

Reply via email to