Skip to content
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

Add Store::call_hook API #1083

Closed
Robbepop opened this issue Jun 24, 2024 · 6 comments
Closed

Add Store::call_hook API #1083

Robbepop opened this issue Jun 24, 2024 · 6 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@Robbepop
Copy link
Member

Robbepop commented Jun 24, 2024

This is about adding a Store::call_hook API similar to Wasmtime's Store::call_hook in order to improve Wasmi's Wasmtime API mirroring.}

This should not regress performance of host function calls or the Wasmi executor generally.

@Robbepop Robbepop added enhancement New feature or request good first issue Good for newcomers labels Jun 24, 2024
@emiltayl
Copy link
Contributor

I have a use case for call_hook, so I figured I could take a shot at this. I now have a working version of call_hook, but had one question.

Should call_hook be behind a feature flag? It seems like a change is coming to wasmtime to put it behind a feature flag, which should make it easier to make sure that this has no/minimal performance impact where it is not needed. I have tried benchmarking with my changes locally and could see some regressions, but I also saw 20% speedups that I can't explain, so I don't know how much I can trust the benchmark numbers on my computer.

@Robbepop
Copy link
Member Author

Hi @emiltayl ,

thank you for working on this feature.

Can you please share a link to the discussion for putting this behind a feature flag? I would like to know more about the reasoning.
From what I can see with the linked PR the feature has not yet been implemented. Is that correct?
What performance regressions are you already seeing?
I imagined that this feature would not have significant performance regressions for Wasmi, since Wasmi being an interpreter will be slowed down but not as harshly as a JIT runtime. Maybe I am wrong about this.

@emiltayl
Copy link
Contributor

The pull request for creating the feature flag is at bytecodealliance/wasmtime#8795, and at bytecodealliance/wasmtime#8808 they disable it by default. It seems to be merged to main, but not put in a release yet if I understand correctly.

I agree that wasmi's performance shouldn't be impacted to a large degree by this change in theory. I don't have the code in front of me right now, but I will be back with the regressions from the benchmarks tomorrow.

@emiltayl
Copy link
Contributor

emiltayl commented Jul 15, 2024

I've included the benchmarks that reported regressions sorted by % change. Judging by the changes I've made, I would have expected to see most change in execute/call/host/* as there is an extra function call on host->wasm and wasm->host boundaries, but I did not get any reported regressions from those benchmarks.

In the instantiate benchmarks an extra None is added when creating Store, but I don't think that should cause a 32% increase in run time. I have not touch linking or module parsing (I'm pretty sure of this at least).

Edit I tried running the benchmarks again on main, comparing with the first benchmark and got comparable results to my call_hook branch, with some benchmarks unexpectedly performing much poorer or slightly better. Seems to be a problem with me running the benchmarks locally. The overhead, especially when no call hook is set, should be quite low.

instantiate/reverse_complement
                        time:   [14.146 µs 14.256 µs 14.354 µs]
                        change: [+30.381% +32.448% +35.163%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high mild

linker/build/construct/same/50
                        time:   [10.326 µs 10.380 µs 10.443 µs]
                        change: [+23.023% +24.755% +26.901%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

instantiate/tiny_keccak time:   [10.863 µs 10.965 µs 11.062 µs]
                        change: [+21.084% +23.059% +25.380%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high mild

linker/setup/same/50    time:   [9.4257 µs 9.4622 µs 9.4998 µs]
                        change: [+12.403% +13.816% +15.746%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 2 outliers among 10 measurements (20.00%)
  1 (10.00%) high mild
  1 (10.00%) high severe

translate/case/best     time:   [82.389 ms 82.601 ms 82.813 ms]
                        change: [+13.051% +13.671% +14.316%] (p = 0.00 < 0.05)
                        Performance has regressed.

execute/br_table        time:   [1.1662 ms 1.1701 ms 1.1777 ms]
                        change: [+8.5328% +10.312% +11.784%] (p = 0.00 < 0.05)
                        Performance has regressed.

translate/reverse_complement/checked/lazy/default
                        time:   [23.113 µs 23.249 µs 23.448 µs]
                        change: [+3.7300% +5.0512% +6.2639%] (p = 0.00 < 0.05)
                        Performance has regressed.

linker/build/finish/unique/50
                        time:   [109.96 ns 110.48 ns 111.05 ns]
                        change: [+3.9326% +5.0184% +6.2214%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 2 outliers among 10 measurements (20.00%)
  1 (10.00%) high mild
  1 (10.00%) high severe

execute/tiny_keccak     time:   [380.57 µs 388.58 µs 395.36 µs]
                        change: [+2.5787% +4.2768% +5.8044%] (p = 0.00 < 0.05)
                        Performance has regressed.

translate/bz2/checked/lazy/default
                        time:   [47.556 µs 47.612 µs 47.658 µs]
                        change: [+2.8848% +3.5006% +4.1674%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

translate/case/worst/stackbomb/10000
                        time:   [115.92 ms 116.61 ms 117.22 ms]
                        change: [+2.0026% +3.2688% +4.4893%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) low mild

translate/reverse_complement/checked/lazy-translation/default
                        time:   [156.43 µs 156.79 µs 157.09 µs]
                        change: [+1.7000% +2.7463% +3.6790%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

@Robbepop
Copy link
Member Author

Hi @emiltayl and sorry for my late reply.

The benchmarks indeed do not look all too good all in all but most of the regressions fortunately are not in the Wasmi executor but in the Wasm module instantiation.
The tiny_keccak Wasmi executor regression is a bit worrysome though since it reflects real-world usage and is usually very stable.

I am not sure how we shall continue with this ideally. The best is if you could open a PR so we could discuss the technical details there but at this point I won't guarantee to merge the efforts if we cannot resolve the regressions or at least soften them.

Robbepop added a commit that referenced this issue Aug 1, 2024
* Start implementing `Store::call_hook` (#1083)

* Add the `Store::call_hook` function, which stores a call hook in `Store`
* Create tests to verify call hook behavior

* Let call hooks return any `wasmi::Error`

* Changed signature of call hooks to return a `wasmi::Error` instead of a `TrapCode`.
* Use `assert_eq!` instead of `assert!` for tests, cosmetic change

* Invoke call hooks on function calls

* An `invoke_call_hook` function in Store to avoid problems with the borrow checker - we need a reference to the underlying data and the stored call hook
* Invoke call hook on host -> wasm and wasm -> host calls

* Clarified documentation on error propagation for call hooks

* Fixed attribute placement and clippy errors

* Placed attributes after doc comments
* Added hint to allow complex type for `generate_error_after_n_calls`

* Fixed clippy warnings on implicit conversion of ! to () in call_hook tests

* Help the compiler optimize function calls for the no call hook scenario

* Inline `Store::invoke_call_hook` to avoid extra function call
* Add a `Store::invoke_call_hook_impl` function that is `#[cold]` to hint that the compiler should optimize for the scenario that there are no call hooks

* Update crates/wasmi/src/store.rs

Co-authored-by: Robin Freyler <[email protected]>

---------

Co-authored-by: Robin Freyler <[email protected]>
@Robbepop
Copy link
Member Author

Robbepop commented Aug 1, 2024

Closed with #1144 being merged.

@Robbepop Robbepop closed this as completed Aug 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants