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
Improve performance of DataPage statistics extraction using StringBuilder #11281
changed the title [-]Further to the performance discussion @alamb - the StringBuilder pattern you suggested in https://github.com/apache/datafusion/pull/11136#discussion_r1657725214 does seem to materially improve performance:[/-][+]Improve performance of DataPage statistics extraction using StringBuilder [/+]on Jul 5, 2024
Ok... after profiling and reading the codes again, I got it about the Strange results got from poc...
The from_iter way is hard to solve the lifetime problem, and to_string() is called to make it, that leads to the extra memory allocation.
Use the StringBuilder directly seems to be the good and easy way to improve performance.
Strange results got from my poc...
After @efredine fixed the filter_map bug in #11295 , we can use StringArray::from_iter to relace collect + StringArray::from.
And the StringArray::from_iter is actually impl like:
let iter = iter.into_iter();letmut builder = GenericByteBuilder::with_capacity(iter.size_hint().0,1024);
builder.extend(iter);
builder.finish()
Extract data page statistics for String/extract_statistics/String
time: [41.303 µs 41.358 µs 41.415 µs]
use StringBuilder directly:
Extract data page statistics for String/extract_statistics/String
time: [15.471 µs 15.489 µs 15.508 µs]
The difference I found now is that the StringBuilder::new use default 1024 as the capacity to init the buffer, but in from_iter side, use size_hint() instead... Maybe it is related to this?
Perhap some profile works needed...
Yes - the primary (initial) problem is that the collection needs to be built so that it owns the references to the items but we want to do that without creating any intermediate values.
Yes - the primary (initial) problem is that the collection needs to be built so that it owns the references to the items but we want to do that without creating any intermediate values.
The choice depends on lifetimes, so perhaps the other one is being invoked and it's not pre-allocating capacity in as efficient a way?
In general, I think you're right that we should be able to eliminate all intermediate vectors.
😂 Sorry, it seems my statement made some misunderstandings?
The reason why from_iter case slow seems due to the to_string() call after I profile it... and I did not notice such to_string call when I first started read the codes...
But still somethings confused me now... When using the builder directly, looping in flatten way is obviously slower than looping it in nested way...
Activity
[-]Further to the performance discussion @alamb - the StringBuilder pattern you suggested in https://github.com/apache/datafusion/pull/11136#discussion_r1657725214 does seem to materially improve performance:[/-][+]Improve performance of DataPage statistics extraction using StringBuilder [/+]Rachelint commentedon Jul 5, 2024
take
Rachelint commentedon Jul 7, 2024
Ok... after profiling and reading the codes again, I got it about the
Strange results got from poc...The
from_iterway is hard to solve the lifetime problem, andto_string()is called to make it, that leads to the extra memory allocation.Use the
StringBuilderdirectly seems to be the good and easy way to improve performance.Strange results got from my poc...
After @efredine fixed the
filter_mapbug in #11295 , we can useStringArray::from_iterto relacecollect + StringArray::from.And the
StringArray::from_iteris actually impl like:It seems that In theory,
from_iteris at least no worse than use theStringBuilderdirectly in #https://github.com/apache/datafusion/pull/11136#discussion_r1657725214...However the bench results are:
collect + fromas origin:from_iter:StringBuilderdirectly:The difference I found now is that the
StringBuilder::newuse default 1024 as the capacity to init the buffer, but infrom_iterside, usesize_hint()instead... Maybe it is related to this?Perhap some profile works needed...
efredine commentedon Jul 7, 2024
Yes - the primary (initial) problem is that the collection needs to be built so that it owns the references to the items but we want to do that without creating any intermediate values.
I would also have naively expected that
from_itershould perform comparably. I did notice that there are two implementations for GenericByteArray and I'm not clear which one would be chosen here:https://github.com/apache/arrow-rs/blob/master/arrow-array/src/array/byte_array.rs#L534-L552
The choice depends on lifetimes, so perhaps the other one is being invoked and it's not pre-allocating capacity in as efficient a way?
In general, I think you're right that we should be able to eliminate all intermediate vectors.
Rachelint commentedon Jul 7, 2024
😂 Sorry, it seems my statement made some misunderstandings?
The reason why
from_itercase slow seems due to theto_string()call after I profile it... and I did not notice suchto_stringcall when I first started read the codes...But still somethings confused me now... When using the builder directly, looping in
flattenway is obviously slower than looping it innestedway...https://github.com/Rachelint/arrow-datafusion/blob/70b9f05e737e81c514259e70a8bd2e9f0ad8e725/datafusion/core/src/datasource/physical_plan/parquet/statistics.rs#L890-L893
https://github.com/Rachelint/arrow-datafusion/blob/70b9f05e737e81c514259e70a8bd2e9f0ad8e725/datafusion/core/src/datasource/physical_plan/parquet/statistics.rs#L909-L913
I can understand some costs exist when using flatten, but it may should not be so obvious?
alamb commentedon Jul 7, 2024
Maybe the compiler is not smart enough to avoid bounds checks or something when using
flatten🤔Rachelint commentedon Jul 8, 2024
Maybe it is actually due to compiler...
I found the same thing in another bench about Boolean...
See https://github.com/Rachelint/arrow-datafusion/blob/82490204e6afecc3f9e15c2ce5d35d7e407f422f/datafusion/core/src/datasource/physical_plan/parquet/statistics.rs#L752-L777