- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1k
Add arrow-avro Decoder Benchmarks #8025
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
Conversation
6bbd823    to
    112ffb7      
    Compare
  
    Introduce benchmarks for the `arrow-avro` decoder to evaluate performance under various scenarios, such as different data types and schemas. Additionally, update the `criterion` and other dependencies, and make the `schema` module public to enable broader usage.
112ffb7    to
    3b39d66      
    Compare
  
    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.
Thanks for the contribution, I executed the benchmark with the command cargo bench --features=arrow,async,test_common,experimental --bench decoder, it can output the time and throughput like below
..... Only part of the result data is retained ....
Nested(Struct)/100      time:   [6.6012 µs 6.6925 µs 6.7970 µs]
                        thrpt:  [145.36 MiB/s 147.63 MiB/s 149.67 MiB/s]
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe
Nested(Struct)/10000    time:   [467.44 µs 470.22 µs 473.82 µs]
                        thrpt:  [224.91 MiB/s 226.63 MiB/s 227.98 MiB/s]
Nested(Struct)/1000000  time:   [3.2511 ms 3.3813 ms 3.5785 ms]
                        thrpt:  [3.1209 GiB/s 3.3030 GiB/s 3.4352 GiB/s]
| "thread_rng", | ||
| ] } | ||
| criterion = { version = "0.6.0", default-features = false } | ||
| criterion = { version = "0.7.0", default-features = false } | 
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.
Are there any features we need in 0.7.0?
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.
I just figured it was a good idea to bump it up. I noticed dependabot was also trying to update it.
| }; | ||
| } | ||
|  | ||
| dataset!(INT_DATA, INT_SCHEMA, gen_int); | 
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.
Nice generation logic
        
          
                arrow-avro/benches/decoder.rs
              
                Outdated
          
        
      | b.iter_batched_ref( | ||
| || new_decoder(schema_json, DEFAULT_BATCH, utf8view), | ||
| |decoder| { | ||
| decoder.decode(black_box(datum)).unwrap(); | 
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.
Do we need the black_box here? From the doc, black_box is used to It prevents the compiler from making optimizations, seems that datum is an array precomputed above.
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.
That is true, I included black_box because I was having difficultly getting consistent benchmarks. I can experiment with removing 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.
I ended up putting the black_box around the entire decoder.decode method call. This was a good catch!
        
          
                arrow-avro/benches/decoder.rs
              
                Outdated
          
        
      | |decoder| { | ||
| decoder.decode(black_box(datum)).unwrap(); | ||
| let batch = decoder.flush().unwrap().unwrap(); | ||
| black_box(batch.get_array_memory_size()); | 
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.
Is the black_box here to make sure that the batch.get_array_memory_size() was executed every time? Is there any reason we want to include get_array_memory_size in the benchmark?
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.
That's a good call out, I'll remove it. We don't need that there.
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.
I went ahead and removed the get_array_memory_size in my latest push.
        
          
                arrow-avro/benches/decoder.rs
              
                Outdated
          
        
      | } | ||
| group.bench_function(BenchmarkId::from_parameter(rows), |b| { | ||
| b.iter_batched_ref( | ||
| || new_decoder(schema_json, DEFAULT_BATCH, utf8view), | 
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.
Not sure if we need to benchmark some other batch size or not
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.
That's a good idea! I can add different batch sizes to this benchmark.
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.
I added benchmarking on different batch sizes in my latest push as well.
| .with_schema(schema) | ||
| .with_batch_size(batch_size) | ||
| .with_utf8_view(utf8view) | ||
| .build_decoder(io::empty()) | 
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.
Is that we use io::empty() here because we always set schema above?
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.
That's about to be removed as .build_decoder doesn't need a Reader once #8006 is finalized and merged in.
| Thanks for the review @klion26 -- @jecsand838 maybe you can address the comments and then I'll take a final review over this PR | 
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.
@jecsand838 thanks for the update, LGTM, cc @alamb
| } | ||
| _ => {} | ||
| } | ||
| group.bench_function(BenchmarkId::from_parameter(rows), |b| { | 
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.
Do we need to add the batch size here?
| Thanks again @jecsand838 and @klion26 for the review. I merged the PR figuring we should continue to move things forward -- let's do any additional things in a follow on PR | 
Which issue does this PR close?
Rationale for this change
This change introduces a comprehensive benchmark suite for the
arrow-avrodecoder. Having robust benchmarks is crucial for several reasons:What changes are included in this PR?
This PR adds a new benchmark file:
arrow-avro/benches/decoder.rs.The key components of this new file are:
Int32,Int64,Float32,Float64,Boolean)Binary(Bytes),String,StringView)Date32,TimeMillis,TimeMicros,TimestampMillis,TimestampMicros,Decimal128,UUID,Interval,Enum)Map,Array,Nested(Struct))FixedSizeBinaryMixedschema with multiple fieldsmod schemapublicAre these changes tested?
These changes are covered by the benchmark tests themselves.
Are there any user-facing changes?
N/A