This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 7c0238a9 fix(parquet): free excluded stats bytes in 
ApplyStatSizeLimits (#885)
7c0238a9 is described below

commit 7c0238a913753ec23700760e06ecc3377c49b863
Author: Mahdi Dibaiee <[email protected]>
AuthorDate: Thu Jul 2 20:08:17 2026 +0100

    fix(parquet): free excluded stats bytes in ApplyStatSizeLimits (#885)
    
    ### Rationale for this change
    
    The current implementation has a memory leak where even if limits are
    set for MinMax statistics, despite not using MinMax after they bypass
    the limit, the code still retains a copy of the bytes, not allowing GC
    to clean them up and accumulating memory.
    
    In our use case we have noticed this causes memory accumulation over
    time and leads to OOMs. After this fix we do not experience the OOMs
    anymore.
    
    ### What changes are included in this PR?
    
    Discard unused Min/Max stats bytes
    
    ### Are these changes tested?
    
    Yes I have tested them in our own codebase
    https://github.com/estuary/connectors
    
    ### Are there any user-facing changes?
    
    No
---
 parquet/metadata/statistics.go | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/parquet/metadata/statistics.go b/parquet/metadata/statistics.go
index e7d8cfcd..9e568403 100644
--- a/parquet/metadata/statistics.go
+++ b/parquet/metadata/statistics.go
@@ -71,12 +71,21 @@ type EncodedStatistics struct {
 // the rationale is that some engines may use the minimum value in the page
 // as the true minimum for aggregations and there is no way to mark that
 // a value has been truncated and is a lower bound and not in the page
+//
+// Excluded values are also cleared here (not just flagged via Has*), since 
this
+// EncodedStatistics is stored as-is in the column chunk's persistent metadata 
by
+// ColumnChunkMetaDataBuilder.SetStats and retained until the file is closed. 
Leaving Max/Min
+// populated after excluding them means the writer keeps a live reference to a 
full copy of every
+// oversized value, once per row group, for the file's entire lifetime -- 
Has*=false alone only
+// affects what gets serialized, not what's retained in memory in the meantime.
 func (e *EncodedStatistics) ApplyStatSizeLimits(length int) {
        if len(e.Max) > length {
                e.HasMax = false
+               e.Max = nil
        }
        if len(e.Min) > length {
                e.HasMin = false
+               e.Min = nil
        }
 }
 

Reply via email to