Skip to content

Rework benchmarks to make it easier to get assembly. - #297

Merged
newpavlov merged 2 commits into
masterfrom
bench
Oct 21, 2022
Merged

Rework benchmarks to make it easier to get assembly.#297
newpavlov merged 2 commits into
masterfrom
bench

Conversation

@josephlr

@josephlrjosephlr commented Oct 21, 2022

Copy link
Copy Markdown
Member

This change:

  • Moves the benchmarks from mod.rs to buffer.rs
  • Passes a &[u8] to test::black_box for both benchmarks
  • Move the inner loop we benchmark into an #[inline(never)] function
  • Includes instructions for getting the ASM for a specific benchmark

This should hopefully reduce the variance of these benchmarks and make it easier to figure out if we are emitting the assembly or IR we expect for a particular implementation.

Signed-off-by: Joe Richey joerichey@google.com

This naming makes more sense, esspecially if we add more benchmark
files.
Signed-off-by: Joe Richey <joerichey@google.com>
@josephlr

josephlr commented Oct 21, 2022

Copy link
Copy Markdown
MemberAuthor

This PR came about because I discovered the amazing cargo-show-asm tool, and I wanted to figure out a way to make it easy to use this tool with our benchmarks.

After installing the tool, we can run cargo asm --bench buffer --release buffer::p384::bench_getrandom::inner. Then after some minor cleanups, we get:

buffer::p384::bench_getrandom::inner:pushrbxsubrsp,64 ; Zero the bufferxorpsxmm0,xmm0movaps xmmword ptr [rsp+48],xmm0movaps xmmword ptr [rsp+32],xmm0movaps xmmword ptr [rsp+16],xmm0 ; Call the funtionlearbx,[rsp+16]movesi,48movrdi,rbxcall qword ptr [rip+ getrandom::imp::getrandom_inner@GOTPCREL] ; Check for errortesteax,eaxjne .LBB17_1 ; test::black_box(slice);mov qword ptr [rsp],rbxmov qword ptr [rsp+8],48movrax,rspaddrsp,64poprbxret

We can see the effect of using getrandom_uninit:

buffer::p384::bench_getrandom_uninit::inner:pushrbxsubrsp,64learbx,[rsp+16]movesi,48movrdi,rbxcall qword ptr [rip+ getrandom::imp::getrandom_inner@GOTPCREL]testeax,eaxjne .LBB18_1mov qword ptr [rsp],rbxmov qword ptr [rsp+8],48movrax,rspaddrsp,64poprbxret

As the benchmarks are compiled as separate crates, we can see the effect of inlining. Removing the #[inline] from getrandom_uninit() gives:

buffer::p384::bench_getrandom_uninit::inner:pushrbxsubrsp,80learbx,[rsp+16]learsi,[rsp+32]movedx,48movrdi,rbxcall qword ptr [rip+ getrandom::getrandom_uninit@GOTPCREL]movrax, qword ptr [rsp+16]testrax,raxje .LBB18_1movrcx, qword ptr [rsp+24]mov qword ptr [rsp+16],raxmov qword ptr [rsp+24],rcxaddrsp,80poprbxret

We can also see that passing the entire array to test::black_box creates an additional copy:

buffer::p384::bench_getrandom_uninit::inner:subrsp,104leardi,[rsp+56]movesi,48call qword ptr [rip+ getrandom::imp::getrandom_inner@GOTPCREL]testeax,eaxjne .LBB18_1 ; 48 byte copymovupsxmm0, xmmword ptr [rsp+56]movupsxmm1, xmmword ptr [rsp+72]movupsxmm2, xmmword ptr [rsp+88]movaps xmmword ptr [rsp+32],xmm2movaps xmmword ptr [rsp+16],xmm1movaps xmmword ptr [rsp],xmm0movrax,rspaddrsp,104ret

@briansmith this relates to #291 (comment) about how the type you pass to black_box affects the code generation, so when comparing implementations, we should be sure to use the same types here.

This change:
- Move the benchmarks from mod.rs to buffer.rs
- Move the inner loop we benchmark into an `#[inline(never)]` function
- Includes instructions for getting the ASM for a specific benchmark
This should hopefully reduce the variance of these benchmarks and make
it easier to figure out if we are emitting the assembly or IR we expect
for a particular implementation.
Signed-off-by: Joe Richey <joerichey@google.com>
@newpavlov
newpavlov merged commit bd0654f into masterOct 21, 2022
@newpavlov
newpavlov deleted the bench branch October 21, 2022 14:10
@briansmith

Copy link
Copy Markdown
Contributor

No major objections from me.

  • Passes a &[u8] to test::black_box for both benchmarks

I think most users don't really want a &[u8] but rather want a [u8; N] or even a stronger type (see the getrandom_array discussion). The getrandom benchmark does produce an [u8; N] but the getrandom_uninit benchmark never does. It is good that you got rid of the extra copy caused by passing the entire array to black_box but it would be better to pass a &[u8; N] instead. In reality the assume_init() call that would be required is almost definitely going to get optimized away; however, according to bug reports from last year that wasn't always the case.

takumi-earth pushed a commit to earthlings-dev/getrandom that referenced this pull request Jan 27, 2026
* Rename benches/mod.rs to benches/buffer.rs
This naming makes more sense, especially if we add more benchmark
files.
Signed-off-by: Joe Richey <joerichey@google.com>
* Rework benchmarks to make it easier to get assembly.
This change:
- Move the benchmarks from mod.rs to buffer.rs
- Move the inner loop we benchmark into an `#[inline(never)]` function
- Includes instructions for getting the ASM for a specific benchmark
This should hopefully reduce the variance of these benchmarks and make
it easier to figure out if we are emitting the assembly or IR we expect
for a particular implementation.
Signed-off-by: Joe Richey <joerichey@google.com>
Signed-off-by: Joe Richey <joerichey@google.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@josephlr@briansmith@newpavlov