Stream: git-wasmtime

Topic: wasmtime / issue #13576 Continuous Sightglass benchmarking


view this post on Zulip Wasmtime GitHub notifications bot (Jun 05 2026 at 22:33):

fitzgen opened issue #13576:

We've wanted continuous Sightglass benchmarking for Cranelift and Wasmtime for a looong time; we are finally getting to the point where we can prioritize it. But first we need to agree exactly what we measure, how we measure it (i.e. high-level consensus on architecture), and what we do with those measurements (i.e. how we display them, what kind of automatic alerting/issue-filing/etc we do).


Benchmarking is hard. Lots of people have opinions on how it should best be done. Historically, this is a topic that has attracted a lot of drive-by opinions. I ask that people kindly refrain from engaging on this issue unless you are regularly hacking on Wasmtime, Cranelift, or Sightglass.


I think we have roughly two separate use cases for continuous benchmarking:

  1. Viewing long-term trends over time. Basically, drawing arewefastyet.com-style graphs where the x axis is ~nightly Wasmtime builds and the y axis is some metric of performance. Gives us a rough sense of how performance today is compared to last week/month/year/etc.

  2. Catching and reporting performance regressions as quickly as we can. Basically, do a statistical significance test between ~yesterday's main and today's main. If the difference is significant and performance got worse, then open an issue detailing the regression's commit range and effect size. Helps us avoid unwittingly regressing performance. This could also be triggered explicitly by Wasmtime/Cranelift maintainers for a particular PR, to compare its performance against main.

These two use cases have (or can have) different requirements:

I just point this out to make sure we don't conflate the two use cases and over-constrain one because of the requirements of the other.


Which measurements should we record?

Sightglass supports recording a variety of measurements:

Doing everything is going to be too noisy and give us information overload. It will also take more resources. So I think we really do want to narrow things down here, ideally to a single measure.

Which should we use for use case (1), long-term trends over time?

Which should we use for use case (2), significance tests between today's and ~yesterday's Wasmtime to catch performance regressions quickly?

How do we measure it?

What's the high-level architecture? Dedicated hardware? How does it integrate into github and actions?

What do we do with it?

We've recorded some benchmark data, what actions do we take based on its results? Do we plot it and serve it on a web page? Do we file issues? Etc...


My Recommendation: Two separate jobs

Use case (1), long-term trends over time

Use case (2), significance tests between today's and ~yesterday's Wasmtime

I could also be convinced we should reuse the virtual wall time data from use case 1, rather than rebenching, but that wouldn't play nice with the benchmark-this-particular-PR-against-main sub-use case.


cc @alexcrichton @cfallin @ricochet

view this post on Zulip Wasmtime GitHub notifications bot (Jun 05 2026 at 23:19):

alexcrichton commented on issue #13576:

Thoughts, in no particular order:

view this post on Zulip Wasmtime GitHub notifications bot (Jun 08 2026 at 16:38):

fitzgen commented on issue #13576:

@alexcrichton

I agree about the most interesting metrics here, but I think we should retain and have a "secondary" display for all metrics we gather. For example in the perf-over-time there'd be a little drop down of all metrics and by default it's be cycles or instructions, but you could set it up to be cache-misses if you really wanted. My hope is that this would be a constant factor more of plumbing to parameterize metrics and generate graphs/divs/etc but wouldn't be too too onerous (even on the storage side of things). I think this would be useful in regression reports since if one "weird" metric regresses and everything else stays the same that's probably still quite interesting.

The tricky bit here isn't the graphing or storage side of things, I don't think.

We can't record all metrics at the same time (e.g. you really don't want to measure wall time while running the programs under valgrind), so I think this would unfortunately mean running the full suite multiple times with different metrics enabled and making a "full run" take N times longer from an outside perspective. That said, we could record all of the perf counters at once or all of the valgrind counters (and the virtual wall time derived from them) at once and have graphs for each of those things, depending on which we chose.

Also, it isn't clear which use case you are thinking about here, but we also probably wouldn't want to mix machine ~independent metrics with machine dependent ones, at least for the trends-over-time use case.

Personally I'm dubious about the assertion that we can use github actions to perform a regression test. I don't dispute that recording/using the same machine reduces the noise, but I'd still predict that despite that it'd be quite noisy. Modeling this as github actions, though, gives us an "out" to eventually doing this on custom hardware (or, rather, rented in some data center). In that sense I don't think I'd change much about this.

Yeah, that's fair and I'm not 100% sure it will work out either. But I agree it is a good place to start, and if we have to move to dedicated hardware or something, then at least we can evolve what we have while maintaining nice github integration.

For comparisons with PRs, you'll want to use the merge-base of main and the PR rather than main in case that's diverged.

Yep, good call.

For trends over time, one piece of data that I think should be collected, per-day, is the commit of the automation repo that the day was using. That way we can track down things like what rustc version was used by looking at the actions configuration.

Ah great point. We should probably capture both the sightlgass commit and the infrastructure commit. Well I guess the latter could presumably allow us to recover the former, so maybe the latter is good enough.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 08 2026 at 18:27):

alexcrichton commented on issue #13576:

Ah ok yeah I misunderstood, I assumed a collection contained all metrics and we selectively threw out some. If we only get a subset of metrics from one run that seems like the place to start. For over-time metrics I'd assume everything would go through callgrind/cachegrind and we wouldn't use perf at all (due to machine variance). For head-to-head runs though running twice to get lots of metrics may be plausible, but if callgrind/cachegrind are good enough over time I figure they'd be reasonable to head-to-head as well.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 09 2026 at 18:56):

cfallin commented on issue #13576:

All of this sounds reasonable to me!

Nick and I talked about quite a bit of this previously; the most interesting question was how to get long-term trends in the face of changing hardware. The callgrind (simulated cache/memory effects) runs get a first-order approximation of that and are (hopefully almost perfectly) deterministic over time.

One other idea I floated was to do a kind of "skiplist differential wallclock run": at any given T, do a differential run against T-1, T-2, T-4, T-8, T-16, T-32, ... (or pick a higher geometric base to go sparser). With the right kind of aggregation, and interpolation, we could combine that with the day-by-day differential run ratios; the "against latest" run disciplines/refines the accumulated error when multiplying day-by-day ratios together over time. (Given a historical recording of all of these logN datapoints per day, we can get from T to any T-k in logN steps and so have asymptotically better error bounds.) That allows us to build wallclock trends over changing underlying hardware.

That's pretty "out there", though, and absolutely we should get the basic thing working first. I'm fully in favor (with only weakly held opinions) of whatever way we can manage to do that.

The only other more strongly-held opinion I have is that I don't think it's worth doing any real wallclock measurements on GitHub runners; they're going to be too noisy. Look at the work that Jamey did back in the day to figure out how to isolate a CPU core for reliable runs: disable interrupts, edit system config to keep all other processes off of a core, pin dynamic core frequency scaling to a fixed frequency, etc. Even then we still had nonzero error bars. For that reason I think it makes sense to focus only on callgrind-produced "synthetic wallclock" plus real instruction counts for now; we're thus portable; and if/when needed we can rent a dedicated machine (not a VM -- same noisy-neighbor problem), isolate a core, and do real measurements that way.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 10 2026 at 20:11):

fitzgen commented on issue #13576:

Thanks Alex and Chris! It sounds like we have consensus on the following as an initial milestone. Please confirm so that we can start building out the infra without having to throw away work or whatever.


Use case (1), long-term trends over time

Use case (2), significance tests between today's and ~yesterday's Wasmtime


Sound good?

view this post on Zulip Wasmtime GitHub notifications bot (Jun 10 2026 at 20:21):

alexcrichton commented on issue #13576:

:+1:

view this post on Zulip Wasmtime GitHub notifications bot (Jun 10 2026 at 20:27):

cfallin commented on issue #13576:

:+1:


Last updated: Jul 29 2026 at 05:03 UTC