This is an automated email from the ASF dual-hosted git repository.
WangzJi pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push:
new 8fcedc3ce5 feature: benchmark tcc real mode (#8062)
8fcedc3ce5 is described below
commit 8fcedc3ce51c17191efb6a88af60c30127fd04c4
Author: zihenzzz <[email protected]>
AuthorDate: Tue Apr 28 13:36:37 2026 +0800
feature: benchmark tcc real mode (#8062)
---
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.x.md | 1 +
test-suite/seata-benchmark-cli/README.md | 63 +++++++++--
test-suite/seata-benchmark-cli/pom.xml | 5 +
.../apache/seata/benchmark/BenchmarkRunner.java | 3 +-
.../seata/benchmark/executor/TCCModeExecutor.java | 116 +++++++++++++++++++--
.../seata/benchmark/tcc/BenchmarkTccAction.java | 45 ++++++++
.../benchmark/tcc/BenchmarkTccActionImpl.java | 44 ++++++++
8 files changed, 256 insertions(+), 22 deletions(-)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 2c81a635bb..5340332485 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -19,6 +19,7 @@ Add changes here for all PR submitted to the 2.x branch.
<!-- Please add the `changes` to the following
location(feature/bugfix/optimize/test) based on the type of PR -->
### feature:
+- [[#8062](https://github.com/apache/incubator-seata/pull/8062)] implement
real TCC mode in benchmark CLI
- [[#8052](https://github.com/apache/incubator-seata/pull/8052)] add
SAGA_ANNOTATION mode to benchmark CLI
- [[#8014](https://github.com/apache/incubator-seata/pull/8014)] add P99.9
latency percentile to benchmark CLI
- [[#7882](https://github.com/apache/incubator-seata/pull/7882)] add metrics
for NamingServer
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 3a9f53f262..95f1bc729a 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -20,6 +20,7 @@
### feature:
+- [[#8062](https://github.com/apache/incubator-seata/pull/8062)] 为benchmark
CLI实现真实TCC模式(try/confirm/cancel)
- [[#8052](https://github.com/apache/incubator-seata/pull/8052)] 为benchmark
CLI新增SAGA_ANNOTATION模式
- [[#7882](https://github.com/apache/incubator-seata/pull/7882)]
为NamingServer增加Metrics监控
- [[#7760](https://github.com/apache/incubator-seata/pull/7760)]
统一Jackson/fastjson序列化器
diff --git a/test-suite/seata-benchmark-cli/README.md
b/test-suite/seata-benchmark-cli/README.md
index 2e6d0b1180..2caedcd89f 100644
--- a/test-suite/seata-benchmark-cli/README.md
+++ b/test-suite/seata-benchmark-cli/README.md
@@ -64,21 +64,23 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode AT \
--tps 100 \
+ --threads 1 \
--duration 60
-# TCC mode benchmark
+# TCC mode benchmark (empty transaction)
java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode TCC \
- --tps 200 \
- --threads 20 \
- --duration 120
+ --tps 100 \
+ --threads 1 \
+ --duration 60
# SAGA mode benchmark (empty transaction)
java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode SAGA \
--tps 100 \
+ --threads 1 \
--duration 60
# SAGA_ANNOTATION mode benchmark (empty transaction)
@@ -86,6 +88,7 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode SAGA_ANNOTATION \
--tps 100 \
+ --threads 1 \
--duration 60
```
@@ -97,6 +100,16 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode AT \
--tps 100 \
+ --threads 1 \
+ --duration 60 \
+ --branches 3
+
+# TCC mode with real try/confirm/cancel
+java -jar seata-benchmark-cli.jar \
+ --server 127.0.0.1:8091 \
+ --mode TCC \
+ --tps 100 \
+ --threads 1 \
--duration 60 \
--branches 3
@@ -105,6 +118,7 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode SAGA \
--tps 100 \
+ --threads 1 \
--duration 60 \
--branches 3 \
--rollback-percentage 5
@@ -114,6 +128,7 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode SAGA \
--tps 100 \
+ --threads 1 \
--duration 60 \
--branches 3 \
--saga-shape order
@@ -123,6 +138,7 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode SAGA \
--tps 100 \
+ --threads 1 \
--duration 60 \
--branches 3 \
--saga-shape order \
@@ -133,6 +149,7 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode SAGA \
--tps 100 \
+ --threads 1 \
--duration 60 \
--branches 3 \
--rollback-percentage 20 \
@@ -506,15 +523,34 @@ java -jar seata-benchmark-cli.jar --server 127.0.0.1:8091
\
--mode SAGA_ANNOTATION --tps 10000 --threads 50 --duration 60 --branches 3
```
-### Test TCC Mode at High Load
+### Test TCC Mode (try/confirm/cancel)
```bash
+# Empty mode: protocol overhead only (fixed TPS)
java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode TCC \
- --tps 500 \
+ --tps 100 \
+ --threads 1 \
+ --duration 60
+
+# Empty mode: max throughput (fixed concurrency)
+java -jar seata-benchmark-cli.jar \
+ --server 127.0.0.1:8091 \
+ --mode TCC \
+ --tps 100000 \
--threads 50 \
- --duration 300
+ --duration 60
+
+# Real mode: 3 branches per transaction, 10% cancel rate
+java -jar seata-benchmark-cli.jar \
+ --server 127.0.0.1:8091 \
+ --mode TCC \
+ --tps 100 \
+ --threads 1 \
+ --duration 60 \
+ --branches 3 \
+ --rollback-percentage 10
```
### Test with Warmup
@@ -524,6 +560,7 @@ java -jar seata-benchmark-cli.jar \
--server 127.0.0.1:8091 \
--mode AT \
--tps 200 \
+ --threads 1 \
--duration 120 \
--warmup-duration 30
```
@@ -535,7 +572,7 @@ java -jar seata-benchmark-cli.jar \
| Mode | Empty Mode (branches=0) | Real Mode (branches>0) |
|------------------|-------------------------|------------------------|
| AT | Pure protocol overhead | MySQL via Testcontainers
(account transfer) |
-| TCC | Mock implementation | Mock implementation |
+| TCC | Pure protocol overhead | Real try/confirm/cancel via
@LocalTCC interceptor |
| SAGA | Mock simulation | State machine engine with
compensation |
| SAGA_ANNOTATION | Pure protocol overhead | Annotation interceptor + TC
compensation callback |
@@ -544,7 +581,7 @@ java -jar seata-benchmark-cli.jar \
For accurate benchmarking of Seata Server capacity, the tool executes **empty
transactions**:
- **AT Mode**: Only `begin()` and `commit()` operations, no SQL execution
-- **TCC Mode**: Empty transaction flow (mock implementation)
+- **TCC Mode**: Empty global transaction, no branch registration
- **SAGA Mode**: Simplified simulation without state machine
- **SAGA_ANNOTATION Mode**: Empty global transaction, no branch registration
@@ -564,6 +601,13 @@ When `--branches` is set to a value greater than 0:
- Executes real account transfer operations
- Each branch performs debit/credit operations
+- **TCC Mode**:
+ - Uses `@LocalTCC` + `@TwoPhaseBusinessAction` annotation path
+ - Each branch is registered via the TCC interceptor (JDK dynamic proxy, no
Spring required)
+ - `try` (prepare) runs in the business thread; `commit` / `rollback` are
invoked by the TC
+ - No-op implementation so the benchmark measures pure TCC protocol overhead
+ - `--branches N` = N TCC branch registrations per transaction
+
- **SAGA Mode**:
- Uses Seata state machine engine
- Executes predefined state machine definitions
@@ -675,7 +719,6 @@ Logs are written to `seata-benchmark.log` in the current
directory.
**v1.1 - Enhancement:**
- P99.9 percentile
-- Real TCC implementation with try/confirm/cancel
- XA mode support
**v2.0 - Advanced Features:**
diff --git a/test-suite/seata-benchmark-cli/pom.xml
b/test-suite/seata-benchmark-cli/pom.xml
index 774145c0d6..410eea45a7 100644
--- a/test-suite/seata-benchmark-cli/pom.xml
+++ b/test-suite/seata-benchmark-cli/pom.xml
@@ -46,6 +46,11 @@
<artifactId>seata-tm</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>seata-tcc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>seata-saga-annotation</artifactId>
diff --git
a/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/BenchmarkRunner.java
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/BenchmarkRunner.java
index 3e5d00ec21..0fda84659c 100644
---
a/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/BenchmarkRunner.java
+++
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/BenchmarkRunner.java
@@ -127,7 +127,8 @@ public class BenchmarkRunner {
System.out.println("Creating AT mode executor" + atMode +
"\n");
return new ATModeExecutor(config);
case TCC:
- System.out.println("Creating TCC mode executor (mock
implementation)\n");
+ String tccMode = isRealMode ? " (try/confirm/cancel)" : "
(empty transaction)";
+ System.out.println("Creating TCC mode executor" + tccMode +
"\n");
return new TCCModeExecutor(config);
case SAGA:
String sagaMode = isRealMode ? " (state machine engine)" : "
(empty transaction)";
diff --git
a/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/executor/TCCModeExecutor.java
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/executor/TCCModeExecutor.java
index b9cb993b21..76fb140cb1 100644
---
a/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/executor/TCCModeExecutor.java
+++
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/executor/TCCModeExecutor.java
@@ -17,41 +17,133 @@
package org.apache.seata.benchmark.executor;
import org.apache.seata.benchmark.config.BenchmarkConfig;
+import org.apache.seata.benchmark.tcc.BenchmarkTccAction;
+import org.apache.seata.benchmark.tcc.BenchmarkTccActionImpl;
+import org.apache.seata.integration.tx.api.interceptor.InvocationWrapper;
+import
org.apache.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler;
+import org.apache.seata.rm.tcc.interceptor.parser.TccActionInterceptorParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
/**
- * TCC mode transaction executor (simplified mock implementation)
- * Note: For Phase 1 (MVP), TCC mode executes empty transactions similar to AT
mode.
- * Full TCC implementation with try/confirm/cancel will be added in future
versions.
+ * TCC mode transaction executor.
+ *
+ * <p>Supports two sub-modes controlled by {@code --branches}:
+ * <ul>
+ * <li><b>Empty mode</b> ({@code branches == 0}): starts and commits an
empty global
+ * transaction. Measures pure Seata protocol overhead with no branch
registration.</li>
+ * <li><b>Real mode</b> ({@code branches > 0}): registers {@code branches}
TCC branches
+ * per transaction via the {@link BenchmarkTccAction} proxy. On commit
the TC invokes
+ * {@link BenchmarkTccAction#commit} for every registered branch; on
rollback it invokes
+ * {@link BenchmarkTccAction#rollback}.</li>
+ * </ul>
+ *
+ * <p>No Spring container is required. A JDK dynamic proxy wraps
+ * {@link org.apache.seata.rm.tcc.interceptor.TccActionInterceptorHandler},
+ * which is equivalent to what Spring AOP would produce at runtime.
*/
public class TCCModeExecutor extends AbstractTransactionExecutor {
private static final Logger LOGGER =
LoggerFactory.getLogger(TCCModeExecutor.class);
+ private BenchmarkTccAction actionProxy;
+ private BenchmarkTccActionImpl actionImpl;
+
public TCCModeExecutor(BenchmarkConfig config) {
super(config);
}
+ private boolean isRealMode() {
+ return config.getBranches() > 0;
+ }
+
@Override
public void init() {
- LOGGER.info("TCC mode executor initialized (simplified mock mode)");
+ if (isRealMode()) {
+ initRealMode();
+ } else {
+ LOGGER.info("TCC mode executor initialized (empty transaction
mode)");
+ }
+ }
+
+ private void initRealMode() {
+ LOGGER.info("Initializing TCC mode executor (try/confirm/cancel)");
+
+ actionImpl = new BenchmarkTccActionImpl();
+
+ // TccActionInterceptorParser does two things:
+ // 1. Registers TCCResource with DefaultResourceManager (enables TC
callbacks)
+ // 2. Returns a TccActionInterceptorHandler for proxy dispatch
+ TccActionInterceptorParser parser = new TccActionInterceptorParser();
+ ProxyInvocationHandler handler;
+ try {
+ handler = parser.parserInterfaceToProxy(actionImpl,
"benchmarkTccService");
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to initialize TCC proxy", e);
+ }
+ if (handler == null) {
+ throw new IllegalStateException(
+ "Failed to initialize TCC proxy: no
@TwoPhaseBusinessAction method was found for "
+ + BenchmarkTccAction.class.getName());
+ }
+
+ // Wrap the handler with a JDK dynamic proxy — equivalent to Spring
AOP proxy
+ actionProxy = (BenchmarkTccAction) Proxy.newProxyInstance(
+ BenchmarkTccAction.class.getClassLoader(),
+ new Class[] {BenchmarkTccAction.class},
+ (proxy, method, args) -> handler.invoke(new
InvocationWrapper() {
+ @Override
+ public Method getMethod() {
+ return method;
+ }
+
+ @Override
+ public Object getProxy() {
+ return proxy;
+ }
+
+ @Override
+ public Object getTarget() {
+ return actionImpl;
+ }
+
+ @Override
+ public Object[] getArguments() {
+ return args;
+ }
+
+ @Override
+ public Object proceed() throws Throwable {
+ return method.invoke(actionImpl, args);
+ }
+ }));
+
+ LOGGER.info("TCC mode executor initialized ({} branches per
transaction)", config.getBranches());
}
@Override
- protected String getTransactionName() {
- return "benchmark-tcc-tx";
+ protected void executeBusinessLogic() throws Exception {
+ if (!isRealMode()) {
+ return;
+ }
+ // Each proxy call triggers the TCC interceptor which registers
+ // one TCC branch with the TC via branchRegister RPC.
+ for (int i = 0; i < config.getBranches(); i++) {
+ actionProxy.prepare(null);
+ }
}
@Override
- protected int getBranchCount() {
- return 0;
+ protected String getTransactionName() {
+ return "benchmark-tcc-tx";
}
@Override
- protected void executeBusinessLogic() throws Exception {
- // Empty transaction - no TCC operations
- // Full TCC with try/confirm/cancel will be implemented in future
versions
+ protected int getBranchCount() {
+ return config.getBranches();
}
@Override
@@ -61,6 +153,8 @@ public class TCCModeExecutor extends
AbstractTransactionExecutor {
@Override
public void destroy() {
+ actionProxy = null;
+ actionImpl = null;
LOGGER.info("TCC mode executor destroyed");
}
}
diff --git
a/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/tcc/BenchmarkTccAction.java
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/tcc/BenchmarkTccAction.java
new file mode 100644
index 0000000000..6aec9445fb
--- /dev/null
+++
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/tcc/BenchmarkTccAction.java
@@ -0,0 +1,45 @@
+/*
+ * 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.seata.benchmark.tcc;
+
+import org.apache.seata.rm.tcc.api.BusinessActionContext;
+import org.apache.seata.rm.tcc.api.LocalTCC;
+import org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * Benchmark TCC action interface.
+ *
+ * <p>Used by {@link org.apache.seata.benchmark.executor.TCCModeExecutor} in
real mode
+ * ({@code branches > 0}) to drive the TCC protocol path through the Seata
interceptor.
+ * Each call to {@link #prepare} registers one TCC branch with the TC. On
global commit
+ * the TC invokes {@link #commit}; on global rollback it invokes {@link
#rollback}.
+ *
+ * <p>All three methods are intentionally no-ops so the benchmark measures
only Seata
+ * protocol overhead, not business logic.
+ */
+@LocalTCC
+public interface BenchmarkTccAction {
+
+ String ACTION_NAME = "seata-benchmark-cli-benchmarkTccAction";
+
+ @TwoPhaseBusinessAction(name = ACTION_NAME, commitMethod = "commit",
rollbackMethod = "rollback")
+ boolean prepare(BusinessActionContext context);
+
+ boolean commit(BusinessActionContext context);
+
+ boolean rollback(BusinessActionContext context);
+}
diff --git
a/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/tcc/BenchmarkTccActionImpl.java
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/tcc/BenchmarkTccActionImpl.java
new file mode 100644
index 0000000000..6db6a0c120
--- /dev/null
+++
b/test-suite/seata-benchmark-cli/src/main/java/org/apache/seata/benchmark/tcc/BenchmarkTccActionImpl.java
@@ -0,0 +1,44 @@
+/*
+ * 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.seata.benchmark.tcc;
+
+import org.apache.seata.rm.tcc.api.BusinessActionContext;
+
+/**
+ * No-op implementation of {@link BenchmarkTccAction}.
+ *
+ * <p>All three TCC phases return immediately so the benchmark measures only
the
+ * Seata TCC protocol overhead (branch registration and TC callbacks), not any
+ * business logic execution time.
+ */
+public class BenchmarkTccActionImpl implements BenchmarkTccAction {
+
+ @Override
+ public boolean prepare(BusinessActionContext context) {
+ return true;
+ }
+
+ @Override
+ public boolean commit(BusinessActionContext context) {
+ return true;
+ }
+
+ @Override
+ public boolean rollback(BusinessActionContext context) {
+ return true;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]