David Mollitor created SPARK-59896:
--------------------------------------

             Summary: Copy a freqItems value only when storing it in the 
counter map
                 Key: SPARK-59896
                 URL: https://issues.apache.org/jira/browse/SPARK-59896
             Project: Spark
          Issue Type: Improvement
          Components: SQL
    Affects Versions: 4.1.0
            Reporter: David Mollitor


h2. Summary

{{{}CollectFrequentItems{}}}, the {{collect_frequent_items}} aggregate behind 
{{{}DataFrame.stat.freqItems{}}}, copies every input value with 
{{InternalRow.copyValue}} before it looks the value up in its item -> count 
map. The copy is only needed when the map stores the value. On a hit, the map 
keeps the key it already has, so the copy is thrown away.
h2. Problem

{{CollectFrequentItems.update}} runs once per input row:
{code:scala}
val key = child.eval(input)
if (key != null) {
  this.add(buffer, InternalRow.copyValue(key), 1L)
} ...
{code}
The copy exists because the evaluated value may point into a reused input 
buffer, so any key the map stores must own its bytes. The copy happens before 
{{add}} knows whether the key is already tracked. For a {{{}UTF8String{}}}, 
{{copyValue}} is {{{}UTF8String.copy(){}}}: a new {{{}byte[]{}}}, a copy of all 
the bytes, and a new {{UTF8String}} object. Struct, array and map values, and 
the {{BinaryView}} values behind {{GEOMETRY}} / {{{}GEOGRAPHY{}}}, are copied 
the same way.

{{freqItems}} is meant for skewed data, where the frequent values keep 
recurring. There, most rows are hits on an existing entry, and for each of them 
the copy is pure overhead.
h2. Proposed change

Pass the evaluated value to {{add}} uncopied, and copy it only where the map 
stores it (the two insert sites in {{{}add{}}}). Incrementing an existing entry 
keeps the entry's stored key, so looking up with a value that points into a 
reused buffer is safe. {{merge}} adds keys from another buffer that already 
owns them, so it keeps not copying. This also removes the null special case in 
{{{}update{}}}, since {{InternalRow.copyValue(null)}} is {{{}null{}}}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to