binary-signal opened a new pull request, #3529:
URL: https://github.com/apache/fluss/pull/3529

   ### Purpose
   
   Linked issue: close #3527
   
   This PR removes the per-record cost which improves write throughput for 
fluss log tables.
   
   ### Brief change log
   
   Two patches:
   
   1. Skip the dynamic-partition check when the table has no partition keys (
      `fluss-client/.../WriterClient.java`):
   
      ```java
      if (!tableInfo.getPartitionKeys().isEmpty()) {
          dynamicPartitionCreator.checkAndCreatePartitionAsync(
                  physicalTablePath,
                  tableInfo.getPartitionKeys(),
                  tableInfo.getTableConfig().getAutoPartitionStrategy());
      }
      ```
   
      `DynamicPartitionCreator.checkAndCreatePartitionAsync` already returns
      immediately when `partitionName == null`. This just hoists the same check 
up
      to the caller so the expensive argument never has to be evaluated. No
      behaviour change.
   
   
   2. Memoise the strategy on `TableConfig` (
      `fluss-common/.../config/TableConfig.java`):
   
      ```java
      public class TableConfig {
          private final Configuration config;
          private volatile AutoPartitionStrategy autoPartitionStrategy;
   
          public AutoPartitionStrategy getAutoPartitionStrategy() {
              AutoPartitionStrategy s = autoPartitionStrategy;
              if (s == null) {
                  s = AutoPartitionStrategy.from(config);
                  autoPartitionStrategy = s; // benign race: same value
              }
              return s;
          }
          ...
      }
      ```
   
      `TableConfig` is immutable after construction. `AutoPartitionStrategy` is
      too with all fields `final`. A volatile field is enough.
   
   ### Tests
   
   No new unit tests. The change is observable only as a perf improvement.
   
   ### Benchmark Performance Improvements
   
   #### Fluss Flink Sink / Taskmanager
   
   | Metric                                         |    Before |     After |  
Delta |
   
|------------------------------------------------|----------:|----------:|-------:|
   | Writer records/s, avg (sum across 16 subtasks) | 2,526,516 | 2,826,183 | 
+11.9% |
   | Writer records/s, peak                         | 3,342,630 | 4,421,649 | 
+32.3% |
   | Writer records/s, p95                          | 3,082,199 | 4,198,872 | 
+36.2% |
   | TaskManager JVM CPU load, avg                  |     51.5% |     44.1% |  
-7.4% |
   | JVM GC time, ms per second, avg                |     1,433 |       999 | 
-30.3% |
   | Writer task busy time, ms/s, avg               |     642.5 |     449.7 | 
-30.0% |
   | Writer task idle time, ms/s, avg               |     357.5 |     550.3 | 
+53.9% |
   | Records per batch, avg                         |    40,971 |    53,531 | 
+30.7% |
   | Bytes per batch, avg                           | 1,267,516 | 1,645,327 | 
+29.8% |
   
   #### Per-record CPU cost
   
   TaskManager level: `cpu_load / throughput`
   
   - Before: 0.515 / 2,526,516 = 204 ns of CPU per record
   - After: 0.441 / 2,826,183 = 156 ns of CPU per record
   - Down 23.5%
   
   Writer-task level: `busy_ms_per_s / throughput`
   
   - Before: 642.5 / 2,526,516 = 254 ns per record
   - After: 449.7 / 2,826,183 = 159 ns per record
   - Down 37.4%
   
   The 37% drop at the writer-task level matches before flamegraph attributed
   roughly half the writer CPU to
   `TimeZone.getTimeZone` plus the `AutoPartitionStrategy.from` construction 
around
   it. Removing both shaves about that much off the per-record cost. The 
remaining
   work (Arrow encoding, ZSTD, serialisation) didn't change.
   
   #### What got faster
   
   Throughput is up at every percentile. Peak and p95 moved more than the mean,
   which fits the picture of the writer no longer being the bottleneck.
   
   CPU is down even though throughput is up. TM doing more records with less
   work.
   
   TM GC time dropped. The fix removes the per-record allocation of
   `AutoPartitionStrategy` and the throwaway `Configuration` view, which is the
   kind of short-lived garbage that drives young-gen churn.
   
   Batches got about 30% bigger by both record count and bytes. With the writer
   faster, the batch window naturally accumulates more records before the 
timeout
   fires, so each RPC carries more payload.
   
   #### Fluss Server-side
   
   
   | Metric                                                            |     
Before |      After |                                         Delta |
   
|-------------------------------------------------------------------|-----------:|-----------:|----------------------------------------------:|
   | `fluss_tabletserver_table_messagesInPerSecond`, avg               |  
2,526,438 |  2,816,269 |                                        +11.5% |
   | `fluss_tabletserver_table_messagesInPerSecond`, peak              |  
3,346,781 |  4,464,978 |                                        +33.4% |
   | `fluss_tabletserver_table_messagesInPerSecond`, p95               |  
3,077,221 |  4,198,341 |                                        +36.4% |
   | `fluss_tabletserver_table_bytesInPerSecond`, avg                  |  77.9 
MB/s |  86.6 MB/s |                                        +11.2% |
   | `fluss_tabletserver_table_bytesInPerSecond`, peak                 | 103.2 
MB/s | 138.1 MB/s |                                        +33.8% |
   | `fluss_tabletserver_table_bytesOutPerSecond`, avg                 |  99.7 
MB/s |  90.0 MB/s |                        -9.7% (see note below) |
   | `fluss_tabletserver_table_totalProduceLogRequestsPerSecond`, avg  |      
149.1 |      186.7 |                                        +25.2% |
   | `fluss_tabletserver_table_totalProduceLogRequestsPerSecond`, peak |      
427.5 |      373.2 | -12.7% (fewer peak RPCs at higher throughput) |
   | `fluss_tabletserver_table_failedProduceLogRequestsPerSecond`      |        
  0 |          0 |                                               |
   
   
   **Flink Task - Fluss Sink Flamegraph Before**
   <img width="1960" height="1450" alt="Screenshot 2026-06-25 at 14 21 58" 
src="https://github.com/user-attachments/assets/71d015f1-96b6-48b6-9df0-67dc1b9904bf";
 />
   
   **Flink Task - Fluss Sink Flamegraph After**
   No trace of getTimezone
   <img width="2688" height="1548" alt="Screenshot 2026-06-24 at 23 24 43" 
src="https://github.com/user-attachments/assets/1e9ef33a-be1f-4a3a-9f8a-9b6b9888ba93";
 />
   
   **Flink** 
   Note: on left hand side is before and on right hand side is after
   
   <img width="3422" height="1086" alt="Screenshot 2026-06-25 at 16 18 32" 
src="https://github.com/user-attachments/assets/6c89415f-a19f-4a20-9b0e-78e1b07f5cbd";
 />
   
   <img width="3422" height="666" alt="Screenshot 2026-06-25 at 16 19 05" 
src="https://github.com/user-attachments/assets/3b95fde9-1dce-47ef-8708-cabcd0098688";
 />
   
   <img width="3422" height="1134" alt="Screenshot 2026-06-25 at 16 19 32" 
src="https://github.com/user-attachments/assets/d0b168fd-b498-4d6f-8c85-e985c29872f6";
 />
   
   <img width="3422" height="600" alt="Screenshot 2026-06-25 at 16 19 51" 
src="https://github.com/user-attachments/assets/44340e67-2826-43a5-b4af-b30f49c08de5";
 />
   
   <img width="3422" height="450" alt="Screenshot 2026-06-25 at 16 20 34" 
src="https://github.com/user-attachments/assets/be725055-8a59-44d9-81fe-371f0a76155d";
 />
   
   <img width="3422" height="500" alt="Screenshot 2026-06-25 at 16 20 50" 
src="https://github.com/user-attachments/assets/e888dcdb-eede-4974-9160-2c5ca7590976";
 />
   
   **Fluss**
   Note: on left hand side is before and on right hand side is after
   
   <img width="3422" height="522" alt="Screenshot 2026-06-25 at 16 21 49" 
src="https://github.com/user-attachments/assets/cb5e10eb-b2ee-43a2-a383-eab36f7eb2b0";
 />
   
   <img width="3422" height="640" alt="Screenshot 2026-06-25 at 16 23 46" 
src="https://github.com/user-attachments/assets/eeb4d19a-5e45-4794-941b-ef6a623c474e";
 />
   
   <img width="3422" height="702" alt="Screenshot 2026-06-25 at 16 25 11" 
src="https://github.com/user-attachments/assets/7bd511a6-a061-4a54-93b3-27054c44ba27";
 />
   
   <img width="3422" height="632" alt="Screenshot 2026-06-25 at 16 27 04" 
src="https://github.com/user-attachments/assets/862763f9-eaad-4c9e-90fa-d5dd87a73f3c";
 />
   
   <img width="3422" height="702" alt="Screenshot 2026-06-25 at 16 28 22" 
src="https://github.com/user-attachments/assets/88d41940-dbb4-423a-bf3b-cbb76ac0f01f";
 />
   
   ### API and Format
   
   No API or storage format changes.
   
   ### Documentation
   
   None needed. No new feature, no user-visible behaviour change.
   


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