goutamadwant opened a new pull request, #13026:
URL: https://github.com/apache/seatunnel/pull/13026

   <!--
   
   Thank you for contributing to SeaTunnel! Please make sure that your code 
changes
   are covered with tests. And in case of new features or big changes
   remember to adjust the documentation.
   
   Feel free to ping committers for the review!
   
   ## Contribution Checklist
     - Make sure that the pull request corresponds to a [GITHUB 
issue](https://github.com/apache/seatunnel/issues).
     - Name the pull request in the form "[Feature] [component] Title of the 
pull request", where *Feature* can be replaced by `Hotfix`, `Bug`, etc.
     - Minor fixes should be named following this pattern: `[hotfix] [docs] Fix 
typo in README.md doc`.
   -->
   
   ### Purpose of this pull request
   
   <!-- Describe the purpose of this pull request. For example: This pull 
request adds checkstyle plugin.-->
   
   Improve SeaTunnel nested Avro serialization by reusing record schemas 
instead of rebuilding them for every ROW, including ROW elements in ARRAYs and 
MAPs.
   
   Fixes #12940. The nullable-ROW prerequisite #12900 is merged.
   
   - Cache schemas within each converter by configured ROW type identity and 
effective record name. Row values and map entry keys cannot grow the cache.
   - Preserve legacy `SeaTunnelRecord` names and the nullable layout's 
enclosing-field names. Different ROW structures with the same leaf name remain 
separate.
   - Build fresh records and values on every serialization. No new dependencies 
or global cache.
   
   Reusing enclosing schema branches directly would change legacy nested 
GenericRecord names. Caching the existing schema-builder results preserves that 
behavior in both layouts; type identity also avoids recursive structural 
hashing on each ROW.
   
   
   
   ### Does this PR introduce _any_ user-facing change?
   
   <!--
   Note that it means *any* user-facing change including all aspects such as 
the documentation fix.
   If yes, please clarify the previous behavior and the change this PR proposes 
- provide the console output, description and/or an example to show the 
behavior difference if possible.
   If possible, please also clarify if this is a user-facing change compared to 
the released SeaTunnel versions or within the unreleased branches such as dev.
   If no, write 'No'.
   If you are adding/modifying connector documents, please follow our new 
specifications: https://github.com/apache/seatunnel/issues/4544.
   -->
   
   No functional, configuration or serialized-data changes. Existing default 
bytes, record names, nullable unions and option defaults are preserved. This is 
an internal allocation optimization.
   
   
   
   ### How was this patch tested?
   
   <!--
   If tests were added, say they were added here. Please make sure to add some 
test cases that check the changes thoroughly including negative and positive 
cases if possible.
   If it was tested in a way different from regular unit tests, please clarify 
how you tested step by step, ideally copy and paste-able, so that other 
reviewers can test and check, and descendants can verify in the future.
   If tests were not added, please describe why they were not added and/or why 
it was difficult to add.
   If you are adding E2E test cases, maybe refer to 
https://github.com/apache/seatunnel/blob/dev/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-cdc-mysql-e2e/src/test/resources/mysqlcdc_to_mysql.conf,
 here is a good example.
   -->
   
   - Avro module verification on Java 11 and Java 17: 24 tests per JDK, zero 
failures/errors/skips.
   - Extended regressions for repeated ROW/ARRAY/MAP conversion, same-named 
rows with different structures, one type under multiple names, changed values 
after cache warm-up, and present/null transitions.
   - Refreshed current-source scoped reactor packaging and Spotless checks 
passed.
   - Official Zeta Java 11 broker E2E: Kafka 3/3 and Pulsar 3/3 passed, zero 
failures/skips/aborts. Both cover nullable nested-row round trip plus the 
existing default Avro write/read methods. Runtime connector/starter hashes 
matched the refreshed packages.
   - The private Pulsar test launcher explicitly exits after successful JUnit 
teardown; natural host-client thread shutdown is not claimed. This harness 
adaptation is outside the source diff.
   - Scoped independent correctness and security reviews completed with no 
actionable findings.
   
   Local serializer measurements used five alternating baseline/candidate JVM 
pairs, 20,000 warm-up and 30,000 measured operations per fixture. Fixtures 
cover flat rows, four nested ROW levels, and ARRAY/MAP containers with 32 ROW 
values, in both nullable layouts. Allocation uses current-thread allocated 
bytes; CPU uses current-thread CPU time. Every payload length and SHA-256 
matched.
   
   On native ARM64 Java 11, median allocation fell 92.0–96.6% and CPU time 
56.8–83.0% for the nested/ARRAY/MAP fixtures. A longer flat control (500,000 
warm-up / 1,000,000 measured operations, five pairs) remained 272 bytes/op; CPU 
median differences were -0.43% and +0.89% for the legacy and nullable layouts.
   
   These are diagnostic serializer measurements, not JMH scores or end-to-end 
throughput results. The measurements were collected against baseline 
`76e11cb80e36b4844ba6820d43e0522dbd912d3c`; the refreshed baseline is 
`403efeee0b3806c77e55c38368abdd41fbf828bd`. Both baseline converter sources are 
identical, and refreshed candidate class bytes match the measured candidate. 
Java 17 checks used an x86 runtime under Rosetta; broker E2E uses Zeta on 
native Java 11 with the pinned amd64 broker images under emulation. Hosted CI 
and other engine/platform coverage remain separate.
   
   
   
   <details>
   <summary>Reproduce the diagnostic serializer measurements</summary>
   
   Use the same source below on baseline 
`403efeee0b3806c77e55c38368abdd41fbf828bd` and candidate 
`5da03b810075c84974cc28a50f7109820602beb3`. Build the format module and 
dependencies for each revision using the normal developer environment. Save the 
source as `NestedAvroBenchmark.java` outside the checkout. Fixture setup and 
output validation run outside the timed loop.
   
   ```bash
   ./mvnw -pl seatunnel-formats/seatunnel-format-avro -am install -DskipTests 
-DskipIT
   ./mvnw -pl seatunnel-formats/seatunnel-format-avro 
dependency:build-classpath -Dmdep.outputFile=/tmp/avro-deps.txt
   avro_cp="seatunnel-formats/seatunnel-format-avro/target/classes:$(cat 
/tmp/avro-deps.txt)"
   javac -cp "$avro_cp" NestedAvroBenchmark.java
   java -Xms256m -Xmx256m -XX:ActiveProcessorCount=2 -cp ".:$avro_cp" 
NestedAvroBenchmark baseline
   # Use the candidate checkout and label for the comparison.
   # Run five fresh pairs, alternating baseline/candidate order.
   ```
   
   ```java
   import com.sun.management.ThreadMXBean;
   import java.lang.management.ManagementFactory;
   import java.security.MessageDigest;
   import java.util.*;
   import org.apache.seatunnel.api.table.type.*;
   import org.apache.seatunnel.format.avro.*;
   
   /** Diagnostic workload using the public Avro serializer. */
   public final class NestedAvroBenchmark {
       private static volatile long blackhole;
       private static final int WARMUP = 20000;
       private static final int MEASURE = 30000;
   
       private static final class Fixture {
           final SeaTunnelRowType type;
           final SeaTunnelRow row;
           Fixture(SeaTunnelRowType t, SeaTunnelRow r) {type=t;row=r;}
       }
       private static Fixture leaf() {
           return new Fixture(new SeaTunnelRowType(new 
String[]{"id","name","enabled","amount"},
               new 
SeaTunnelDataType<?>[]{BasicType.INT_TYPE,BasicType.STRING_TYPE,BasicType.BOOLEAN_TYPE,BasicType.LONG_TYPE}),
               new SeaTunnelRow(new 
Object[]{123,"sample-nested-data",true,123456789L}));
       }
       private static Fixture fixture(String kind) {
           Fixture f=leaf();
           if(kind.equals("flat")) return f;
           if(kind.equals("nested")) {
               for(int depth=0;depth<4;depth++) {
                   f=new Fixture(new SeaTunnelRowType(new 
String[]{"detail","sequence"},new 
SeaTunnelDataType<?>[]{f.type,BasicType.INT_TYPE}),new SeaTunnelRow(new 
Object[]{f.row,depth}));
               }
               return f;
           }
           if(kind.equals("array32")) {
               SeaTunnelRow[] items=new 
SeaTunnelRow[32];Arrays.fill(items,f.row);
               return new Fixture(new SeaTunnelRowType(new 
String[]{"items"},new SeaTunnelDataType<?>[]{ArrayType.of(f.type)}),new 
SeaTunnelRow(new Object[]{items}));
           }
           Map<String,SeaTunnelRow> items=new LinkedHashMap<>();
           for(int i=0;i<32;i++)items.put("item"+i,f.row);
           return new Fixture(new SeaTunnelRowType(new String[]{"items"},new 
SeaTunnelDataType<?>[]{new MapType<>(BasicType.STRING_TYPE,f.type)}),new 
SeaTunnelRow(new Object[]{items}));
       }
       private static String hex(byte[] data) {StringBuilder s=new 
StringBuilder();for(byte b:data)s.append(String.format("%02x",b));return 
s.toString();}
       public static void main(String[] args) throws Exception {
           ThreadMXBean bean=(ThreadMXBean)ManagementFactory.getThreadMXBean();
           
bean.setThreadAllocatedMemoryEnabled(true);bean.setThreadCpuTimeEnabled(true);
           long tid=Thread.currentThread().getId();
           
System.out.println("label,java,kind,nullable,iterations,bytes_per_op,cpu_ns_per_op,wall_ns_per_op,payload_bytes,sha256");
           for(String kind:new String[]{"flat","nested","array32","map32"}) 
for(boolean nullable:new boolean[]{false,true}) {
               Fixture fixture=fixture(kind);AvroSerializationSchema 
serializer=new AvroSerializationSchema(fixture.type,nullable);
               byte[] reference=serializer.serialize(fixture.row);
               for(int 
i=0;i<WARMUP;i++)blackhole+=serializer.serialize(fixture.row).length;
               long 
allocated=bean.getThreadAllocatedBytes(tid),cpu=bean.getCurrentThreadCpuTime(),start=System.nanoTime();
               for(int i=0;i<MEASURE;i++) {byte[] 
out=serializer.serialize(fixture.row);blackhole+=out.length;}
               long 
elapsed=System.nanoTime()-start,usedCpu=bean.getCurrentThreadCpuTime()-cpu,usedBytes=bean.getThreadAllocatedBytes(tid)-allocated;
               
System.out.printf(Locale.ROOT,"%s,%s,%s,%s,%d,%.2f,%.2f,%.2f,%d,%s%n",args[0],System.getProperty("java.version"),kind,nullable,MEASURE,(double)usedBytes/MEASURE,(double)usedCpu/MEASURE,(double)elapsed/MEASURE,reference.length,hex(MessageDigest.getInstance("SHA-256").digest(reference)));
           }
       }
   }
   ```
   
   </details>
   
   ### Check list
   
   * [ ] If any new Jar binary package adding in your PR, please add License 
Notice according
     [New License 
Guide](https://github.com/apache/seatunnel/blob/dev/docs/en/developer/new-license.md)
   * [ ] If necessary, please update the documentation to describe the new 
feature. https://github.com/apache/seatunnel/tree/dev/docs
   * [ ] If necessary, please update `incompatible-changes.md` to describe the 
incompatibility caused by this PR.
   * [ ] If you are contributing the connector code, please check that the 
following files are updated:
     1. Update 
[plugin-mapping.properties](https://github.com/apache/seatunnel/blob/dev/plugin-mapping.properties)
 and add new connector information in it
     2. Update the pom file of 
[seatunnel-dist](https://github.com/apache/seatunnel/blob/dev/seatunnel-dist/pom.xml)
     3. Add ci label in 
[label-scope-conf](https://github.com/apache/seatunnel/blob/dev/.github/workflows/labeler/label-scope-conf.yml)
     4. Add e2e testcase in 
[seatunnel-e2e](https://github.com/apache/seatunnel/tree/dev/seatunnel-e2e/seatunnel-connector-v2-e2e/)
     5. Update connector 
[plugin_config](https://github.com/apache/seatunnel/blob/dev/config/plugin_config)
   
   No new binary dependencies, connector registration changes, public API 
changes or incompatible data formats are introduced.
   


-- 
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