nzw921rx opened a new issue, #12074: URL: https://github.com/apache/seatunnel/issues/12074
### Search before asking - [x] I had searched in the [feature](https://github.com/apache/seatunnel/issues?q=is%3Aissue+label%3A%22Feature%22) and found no similar feature requirement. ### Description This is a performance optimization challenge for all serialization and deserialization paths covered by `DebeziumJsonFormatBenchmark`: - `deserializeInsertEvent` - `deserializeUpdateEvent` - `serializeInsertEvent` - `serializeMergedUpdateEvent` It is not a performance regression report or a Java version comparison. The goal is to identify avoidable CPU and allocation overhead in the production Debezium JSON format implementation, implement focused optimizations, and evaluate every benchmark method before and after the change. ## Benchmark evidence The normal JMH results were collected on GitHub-hosted Ubuntu runners: https://github.com/apache/seatunnel/actions/runs/33755882968 | Benchmark | Java 8 Score | Java 8 CV | Java 11 Score | Java 11 CV | Unit | | --- | ---: | ---: | ---: | ---: | --- | | `deserializeInsertEvent` | `534.905` | `1.27%` | `327.902` | `1.77%` | `ops/ms` | | `deserializeUpdateEvent` | `367.594` | `1.07%` | `234.749` | `1.30%` | `ops/ms` | | `serializeInsertEvent` | `619.157` | `0.98%` | `477.362` | `0.68%` | `ops/ms` | | `serializeMergedUpdateEvent` | `386.696` | `0.47%` | `311.864` | `0.99%` | `ops/ms` | Absolute Score depends on the runner. Before-and-after comparisons should therefore use the same JDK, benchmark configuration, and execution environment. ## Diagnostic evidence The following diagnostic run profiled `deserializeInsertEvent` with Java 11: https://github.com/apache/seatunnel/actions/runs/33775288533 Configuration: - JDK: Temurin 11.0.32 - Threads: 1 - Forks: 1 - Warmup: 3 iterations, 10 seconds each - Measurement: 5 iterations, 10 seconds each ### GC and allocation | Metric | Result | | --- | ---: | | Diagnostic throughput | `317.564 +/- 2.605 ops/ms` | | Measurement range | `316.649-318.298 ops/ms` | | Throughput CV | approximately `0.21%` | | Allocation per event | `5,176.492 B/op` | | Allocation rate | `1,567.490 MB/sec` | | G1 Eden churn | `5,196.515 B/op` | | G1 Old Gen churn | `0.010 B/op` | | GC count | `305` | | GC time | `209 ms` | The allocation result was consistent across all measurement iterations: ```text 5176.497 5176.495 5176.492 5176.487 5176.487 B/op ``` The negligible Old Gen churn indicates that this is primarily short-lived allocation rather than retained-memory growth. At the measured throughput, the benchmark creates approximately `1.57 GB/sec` of temporary objects. Profiler overhead makes the diagnostic Score unsuitable as the normal throughput baseline. Its `gc.alloc.rate.norm` result is the allocation baseline for this method. ### CPU profile The CPU diagnostic collected `5,032` async-profiler samples. A coarse grouping of flat-profile self-time shows approximately `53%` in Jackson parsing and JSON node operations and approximately `19%` in `HashMap` and `LinkedHashMap` operations. The map operations appear in stacks below Jackson `ObjectNode` construction. Representative hot methods include: | Method | Sampled self-time | | --- | ---: | | `java.util.HashMap.putVal` | `6.88%` | | `UTF8StreamJsonParser.nextFieldName` | `4.47%` | | `java.util.HashMap.resize` | `4.07%` | | `UTF8StreamJsonParser._finishAndReturnString` | `3.82%` | | `UTF8StreamJsonParser._parseUnsignedNumber` | `3.42%` | | `ByteQuadsCanonicalizer.findName` | `3.20%` | | `UTF8StreamJsonParser._parseName` | `3.16%` | | `java.util.HashMap$Node.<init>` | `2.48%` | | `SeaTunnelRow.<init>` | `2.01%` | | `DebeziumRowConverter.getValue` | `1.63%` | The dominant call path is: ```text ObjectMapper.readTree -> JsonNodeDeserializer -> BaseNodeDeserializer -> ObjectNode.replace -> HashMap.put / resize -> DebeziumJsonDeserializationSchema.deserializeMessage ``` This provides an initial investigation point for deserialization. Serialization should be profiled independently before selecting its optimization approach. ## Challenge targets This issue is a challenge rather than a task with strict acceptance thresholds. The throughput challenge is approximately `10%` above the current Java 11 reference results: | Benchmark | Reference Score | Challenge target | | --- | ---: | ---: | | `deserializeInsertEvent` | `327.902 ops/ms` | approximately `361 ops/ms` | | `deserializeUpdateEvent` | `234.749 ops/ms` | approximately `258 ops/ms` | | `serializeInsertEvent` | `477.362 ops/ms` | approximately `525 ops/ms` | | `serializeMergedUpdateEvent` | `311.864 ops/ms` | approximately `343 ops/ms` | For allocation, the challenge target is approximately `20%` below each method's baseline. The currently established target for `deserializeInsertEvent` is: ```text Baseline: 5,176.492 B/op Challenge target: approximately 4,100 B/op or lower ``` The other three methods should establish their `gc.alloc.rate.norm` baselines before optimization. These values are aspirational rather than mandatory acceptance criteria. A smaller but reproducible improvement is still valuable when the contribution identifies the optimized source and explains the result. ## Expected result The contribution should: 1. Profile and evaluate all four benchmark methods. 2. Identify the relevant CPU or allocation source using profiling evidence. 3. Implement a production-code optimization rather than stopping after analysis. 4. Report before-and-after `Score`, `Error`, `CV`, and `gc.alloc.rate.norm` for all four methods under equivalent conditions. 5. Avoid a reproducible regression in benchmark methods not directly improved by the change. ## Reproduction The `Benchmarks Diagnostics` workflow accepts one exact benchmark method per run. Select Java 8 or Java 11 and use `cpu`, `wall`, `lock`, `gc`, or `all` as required. The methods can also be profiled locally, for example: ```bash bash tools/benchmarks/profile_benchmarks.sh profile gc \ --benchmark 'DebeziumJsonFormatBenchmark.deserializeInsertEvent$' bash tools/benchmarks/profile_benchmarks.sh profile cpu \ --benchmark 'DebeziumJsonFormatBenchmark.deserializeInsertEvent$' ``` Repeat the command with each of the other three exact method names. See the benchmark guide for profiler setup, workflow usage, and result interpretation: https://seatunnel.apache.org/docs/engines/zeta/benchmark ### Usage Scenario _No response_ ### Related issues _No response_ ### Are you willing to submit a PR? - [ ] Yes I am willing to submit a PR! ### Code of Conduct - [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
