You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature] Improve scan performance in hot read paths #240
I searched in the issues and found nothing similar.
Motivation
Recent profiling of highly concurrent scans has revealed several performance bottlenecks caused by
repeated operations on Arrow-returned shared_ptr objects in hot read loops.
Two significant cases have been identified:
Manifest readers repeatedly call StructArray::fields() while processing individual rows. This
copies shared_ptr<Array> objects and, with GCC 8.3's libstdc++, can introduce substantial lock
contention through _Sp_locker, pthread_mutex_lock, and futex waits when multiple workers read
manifests concurrently.
Avro decoding calls ArrayBuilder::type() for every integer and timestamp value. Because this
method returns std::shared_ptr<DataType> by value, concurrent scans repeatedly modify reference
counts on shared Arrow primitive data types, causing cache-line contention. Profiling showed ArrayBuilder::type() and shared-pointer release operations accounting for a large proportion of
samples after the manifest bottleneck was removed.
This issue tracks the broader effort to identify and eliminate similar shared-pointer operations
from scan hot paths. The goal is to cache immutable Arrow metadata at an appropriate batch, reader,
or builder lifetime, while ensuring caches are invalidated whenever the corresponding Arrow object
tree is replaced.
The expected outcome is lower synchronization and reference-counting overhead under concurrent
scans, allowing CPU time to return to actual decoding, memory copying, and buffer management.
changed the title [-][Feature] Improve scan performance by reducing shared_ptr contention in hot read paths[/-][+][Feature] Improve scan performance in hot read paths[/+]on Aug 24, 2026
A follow-up PR has been opened for this issue: #242
After profiling the updated implementation, several additional sources of Arrow-side overhead remained.
This follow-up PR focuses on three areas:
Avoid redundant Arrow array validation
Arrays produced by controlled Avro builders were validated again after Finish(). For nested Struct, List, and Map types, this validation recursively compares data types and computes type fingerprints.
The PR skips this validation in release builds while retaining it in debug builds for invariant checking.
Reuse ColumnarRow within a manifest batch
The manifest bucket scan previously constructed and destroyed one ColumnarRow per row, although the underlying Arrow fields and memory pool remain unchanged throughout the batch.
The PR creates one row view per batch and updates only its row index during iteration.
Reserve Avro builder capacity
The target batch size is known before decoding, but Arrow builders previously relied on progressive capacity growth.
The PR reserves capacity for the root builder and same-cardinality Struct children using the configured batch size. List and Map child builders are reserved using their decoded Avro block sizes, since their element cardinality is not known in advance.
These changes target management overhead rather than Avro decoding or decompression itself, reducing repeated validation, object lifecycle operations, memory reallocations, and data copying.
Activity
[-][Feature] Improve scan performance by reducing shared_ptr contention in hot read paths[/-][+][Feature] Improve scan performance in hot read paths[/+]gripleaf commentedon Aug 24, 2026
A follow-up PR has been opened for this issue: #242
After profiling the updated implementation, several additional sources of Arrow-side overhead remained.
This follow-up PR focuses on three areas:
Avoid redundant Arrow array validation
Arrays produced by controlled Avro builders were validated again after
Finish(). For nested Struct, List, and Map types, this validation recursively compares data types and computes type fingerprints.The PR skips this validation in release builds while retaining it in debug builds for invariant checking.
Reuse
ColumnarRowwithin a manifest batchThe manifest bucket scan previously constructed and destroyed one
ColumnarRowper row, although the underlying Arrow fields and memory pool remain unchanged throughout the batch.The PR creates one row view per batch and updates only its row index during iteration.
Reserve Avro builder capacity
The target batch size is known before decoding, but Arrow builders previously relied on progressive capacity growth.
The PR reserves capacity for the root builder and same-cardinality Struct children using the configured batch size. List and Map child builders are reserved using their decoded Avro block sizes, since their element cardinality is not known in advance.
These changes target management overhead rather than Avro decoding or decompression itself, reducing repeated validation, object lifecycle operations, memory reallocations, and data copying.