eeriee opened a new pull request, #23203:
URL: https://github.com/apache/kafka/pull/23203

   RecordAccumulator.ready() runs once per partition, and its per-partition 
helpers run once per batch, on every Sender runOnce() cycle. This makes the 
per-partition/per-batch cost matter most for producers with many partitions. 
This change makes four related improvements:
   
   1. Key batches by TopicPartition instead of partition int
   
      Deques of ProducerBatch were previously keyed by a raw partition int, 
requiring a TopicPartition -> int mapping step and making it easy to 
accidentally mix up partitions across topics that share the same partition 
number. Keying directly by TopicPartition removes that indirection and the 
associated bookkeeping.
   
   2. Defer Cluster.leaderFor() / MetadataSnapshot.leaderEpochFor() until after 
the empty-deque check, and short-circuit further per-batch computation when 
nothing changed
   
      Previously, partitionReady() looked up the leader node and leader epoch 
for a partition before checking whether its deque had a batch at all. Since the 
overwhelming majority of partitions have an empty deque on any given cycle 
(most producers only actively send to a small subset of their partitions at 
once), this meant paying for a Cluster/TopicPartition-keyed lookup on every 
partition, every cycle, for no reason. The lookups are now deferred until after 
confirming the deque actually has a batch, and a checkBatchReady flag lets the 
subsequent waitedTimeMs/backingOff/full computation and the readyNodes/muted 
check in batchReady() be skipped entirely when the fast paths already 
determined the partition isn't ready.
   
      MetadataSnapshot.clusterInstance is now computed eagerly at construction 
time and stored in a final field (rather than lazily computed and null-checked 
on every cluster() call), which is safe since a MetadataSnapshot's underlying 
metadata never changes after construction.
   
   3. Guard trace logging in ProducerBatch.maybeUpdateLeaderEpoch
   
      Both branches called log.trace(...) unconditionally with several varargs, 
so every call allocated a varargs array and boxed an int even when trace 
logging was disabled. This method runs once per batch on every 
ready()/partitionReady() cycle, so at high partition counts the allocation 
overhead adds up. Guard both calls with log.isTraceEnabled(), matching the 
existing pattern already used elsewhere in RecordAccumulator/Sender for 
identically shaped trace logging.
   
   4. Avoid redundant trace logging in 
BuiltInPartitioner.updatePartitionLoadStats
   
      Only log/reset partitionLoadStatsHolder when actually transitioning out 
of adaptive mode (i.e. it was previously non-null), instead of unconditionally 
whenever queueSizes is null. Previously this ran on every ready() cycle for 
every topic not in adaptive mode, and log.trace()'s internal isTraceEnabled() 
check can itself be expensive depending on the logging backend's filter chain, 
so this should be avoided entirely in the (common, steady-state) case where 
adaptive partitioning was already off on the prior call.
   
   Also adds a JMH benchmark, RecordAccumulatorReadyBenchmark, covering ready() 
with a large partition count and only a small fraction of partitions having a 
pending batch (the common case), parameterized on topic count and on whether 
adaptive partitioning is enabled.
   
   Delete this text and replace it with a detailed description of your change. 
The 
   PR title and body will become the squashed commit message.
   
   If you would like to tag individuals, add some commentary, upload images, or
   include other supplemental information that should not be part of the 
eventual
   commit message, please use a separate comment.
   
   If applicable, please include a summary of the testing strategy (including 
   rationale) for the proposed change. Unit and/or integration tests are 
expected
   for any behavior change and system tests should be considered for larger
   changes.
   


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