Repository navigation
Record which machine ran a test, and make performance comparisons machine-aware #301
Description
The regression reports decide that something got slower by comparing a run of a branch against the previous run of the same branch:
# all-reports.py
timeMinPhase = 4 # Need to have completed code generation to report performance regressions
timeRel = 1.7 # Minimum 1.7x time is registered as a performance regression
timeAbs = 10 # Ignore performance regressions for times <10s...It pairs consecutive dates of a branch from omcversion and flags a phase that took 1.7 times longer. That is sound as long as both runs happened on the same hardware, which until now they did, because each job was pinned to its machine.
That assumption is going away. Jobs are being shared between machines, and while ryzen-5950x-1 and ryzen-5950x-2 are the same model, a faster machine such as a ryzen-9950x is a different generation - and the difference will be largest exactly where the testing spends its time, compiling one model at a time, rather than spread evenly over the phases.
Two things then go wrong, and only one of them is noisy:
- a branch that runs on the fast machine one night and a slower one the next gets longer times with no change in OpenModelica, and every model that crosses 1.7x produces a regression and an email;
- a real regression that lands on the faster machine is hidden, which nobody notices at all.
What the database would need
Nothing records which machine produced a result. job_claim knows the host while a run is in progress, but that is not kept, and omcversion says only which compiler was used.
One row per run, keyed the way a run is already identified:
CREATE TABLE machine (
branch text NOT NULL,
date bigint NOT NULL,
host text NOT NULL, -- socket.gethostname(), as job_claim already uses
cpu text, -- what cpu_name() reads out of /proc/cpuinfo
cores integer,
memory_gb integer,
system text, -- lsb_release
PRIMARY KEY (branch, date)
);test.py already computes all of it for the HTML header and then throws it away:
sysInfo = "%s, %d GB RAM, %s%s" % (cpu_name(), memory_gb, docker, lsb_release)so storing it is mostly plumbing.
Suggested order
- Record the machine of every run. Cheap, and the prerequisite for the rest.
- Make the comparison machine-aware.
all-reports.pyshould either compare a run against the previous run on the same machine, or mark a comparison across machines as not a performance signal. This is the part that has to exist before a machine of a different speed joins, otherwise the first mixed night is all noise. - Then, if cross-machine numbers should be comparable, measure the ratio rather than guess it. A fixed model timed once per run - the testing already builds
HelloWorldfor its feature checks, so it is nearly free - gives an index per run. After a few runs it also shows how noisy that index is on one machine, which decides whether scaling by it is meaningful at all. A single number cannot really capture it: compile time is dominated by single-core speed and I/O, simulation by the CPU, and both depend on how many tests run in parallel.
I would not apply a correction factor silently in any case. Saying "this run came from a machine that measured 1.4 times slower" is honest; multiplying the numbers and presenting them as comparable is not.
Meanwhile
Jobs are being split so that the same libraries run on the same machine, which keeps the comparisons valid without any of the above.
Context: part of the network database work in #295, which is what made sharing jobs between machines possible in the first place.
Generated by Claude Code.
Activity
cbu-hw commentedon Aug 12, 2026
It seems to me like this is the sane way to proceed.
Keep in mind that if jobs change machines in some "random" fashion, it might happen that a performance comparison to an earlier run on the same machine might mean that that comparison baseline is N>>1 days old, thus attributing e.g. an observed performance regression to a wide range of commits (or, wrongly, to the latest commit) -- that must be fun to hunt down the actual commit that caused the regression. :-/
adrpo commentedon Aug 12, 2026
Yes. I am just brainstorming a bit. For now I will keep the same set of jobs running on the same machine so the performance numbers are similar.
adrpo commentedon Aug 21, 2026
#320 does the recording half of this.
One design difference worth flagging: instead of the
machine (branch, date)tableproposed here, it puts
hostandsysinfoonlibversion, which is already keyed(date, branch, libname). A table keyed per run cannot express "ExternalMedia ran onryzen-5950x-1and Buildings onryzen-5950x-2in the same run", and that is exactly thesituation this issue exists because of — jobs are claimed per library now, not pinned per
machine, so the machine is a property of a library's results rather than of a run. It also
avoids a new table and a new join: every reader that wants the library version already
selects from
libversion.sysinfois stored as the same string the report shows rather than split intocpu/cores/memory_gb/system. The comparison this issue is really about only needs
hostequality; the rest is for a human reading the report. Happy to split it out if you would
rather have the columns.
The second half — teaching
all-reports.pyto skip the 1.7x performance comparison whenthe two dates it is pairing have different hosts — is not in #320. It needs the data
to exist for a while first: every row already in the database reads back
NULL, so thecomparison has nothing to go on until a branch has two runs recorded with a host.
Worth reading together with #295's remaining Docker task. What surfaced this was
ExternalMedia and Buildings'
Utilities.IO.Python_3_8.*flipping in exact anti-phase onmaster for ten consecutive run pairs — ExternalMedia will not load on the Ubuntu 22.04
node, and python3.8 does not exist on the Ubuntu 24.04 nodes. Recording the host makes
that diagnosable; one image for every node makes it not happen.
generated by Claude Code
Record the node a container is running on, not the container id (#322)