-
Notifications
You must be signed in to change notification settings - Fork 761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
serializer without tmp alloc. #5451
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Ignored Deployment
|
Thanks for the contribution! Please review the labels and make any necessary changes. |
&self, | ||
column: &'a ColumnRef, | ||
format: &FormatSettings, | ||
) -> Result<Box<dyn StreamingIterator<Item = [u8]> + 'a>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this dyn iterator make virtual call next
slow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's ok, it's more worthy than tmp alloc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a little worried about it too, not have much experience of it, let me do a simple bench for comparing first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple bench with Criterion show 4 to 5 times faster for not nullable i32
https://gist.github.com/youngsofun/75c6420bf51fe4c63e19aa303d2e4f9d
@sundy-li
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we can't avoid virtual call, how about using row based API?
Refer to clickhouse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need another bench for the performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sundy-li ok, I`ll try it later, worked on a bugfix today, almost done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sundy-li
the output of the current bench:
https://gist.github.com/youngsofun/b7a2d3629e53aa6d6cdfb72d82a8a727
fn write_csv_field(&self, column, row_num, &mut buf)
is faster then stream_iterator for short columns, but a little slow for long ones. I think both are ok.
only test int32 today, tided up the code, will go on with nullable and string tomorrow.
stream_iterator needs an extra copy from tmp buf inside iterator, may slow down when the string is long, but may not be too bad if it is in cache?
let v = col.get_data_owned(row_num); | ||
lexical_to_bytes_mut_no_clear(v, buf); | ||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sundy-li is this what you expected? can it be faster?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it might be faster I think. With row-based API we could write reusable codes without extra allocation. Need a bench to verify it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use Criterion::default().with_profiler(perf::FlamegraphProfiler::new(100);
to have the flamegraph, thus we can get the bottle neck.
|
2^10, 2^12, 2^14
|
shortcoming
replace |
buf: &mut Vec<u8>, | ||
_format: &FormatSettings, | ||
) -> Result<()> { | ||
let col: &<Vec<u8> as Scalar>::ColumnType = unsafe { Series::static_cast(&column) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&StringColumn
is ok
Great result of benchmarks, it seems row based API is more simple & efficient than iter API. I just came up with another approach, we can hold a column reference inside the serializer (eg: &[i32] for ColumnI32), it might be faster than others ? |
ok, I`ll try it later. |
Seems the bottleneck is converting an integer to String, I would like to choose index-row-based API, what do you think ? |
embeded(i.e.
even worse for short column
|
agree that row-based is simpler than stream iterator, and is enough for serialization. maybe we need another
and this type can impl serialization interface. |
replace |
@sundy-li do you know why not-embeded is much slower than embeded for int32 but not for string? https://gist.github.com/youngsofun/e33f3a8e0d1fbd8882c74f4b7a7d2131 |
|
new pr #5791 |
I hereby agree to the terms of the CLA available at: https://databend.rs/dev/policies/cla/
Summary
Summary about this PR
current serializer return Vec of tmp strings.
arrow2 reuse buf in streaming iterator.
https://github.com/jorgecarleitao/arrow2/blob/47edf30128/src/io/csv/write/serialize.rs
the first commit is to findout a way to adopting streaming-iterator to our datavalues( especially for nullable column).
this pr reported a improvement of 20% -25%
jorgecarleitao/arrow2#382
need bench to know how much faster it will be for us.
Changelog
Related Issues
Fixes #issue