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]

Reply via email to