Re-measure the whole fleet at render v0.21.0 - #24
Merged
Conversation
tannevaled
force-pushed
the
baseline-render-v0.21.0
branch
from
August 31, 2026 16:50
0483582 to
40977d4
Compare
tannevaled
marked this pull request as ready for review
August 31, 2026 16:55
tannevaled
force-pushed
the
baseline-render-v0.21.0
branch
from
August 31, 2026 17:09
287c3f8 to
119214b
Compare
pdfimages lists a /CalRGB picture as "rgb" and a /CalGray one as "gray" (utils/ImageOutputDev.cc:159-164), while the pixels it writes went through colorMap->getRGB (:451) — for a GfxCalRGBColorSpace, the gamma, the matrix and the chromatic adaptation. So the direct bucket admitted pictures poppler HAD converted, and measured every pixel of them against a colour conversion we did not make. All four pictures still differing by more than four levels after render v0.21.0's chroma fix were CalRGB. The bucket is now decided by both sides: a picture is converted when the listing says so, and also when its own /ColorSpace resolves to CalRGB, CalGray, ICCBased or Lab, whatever the listing says. Only the first two can move anything — poppler lists ICCBased as "icc" and Lab as "lab", both converted already — and all four are named so the rule is a statement about the document rather than a patch over one judge's table. The space is read from the picture's own dictionary, through the page's forms as render.Images walks them and to the same depth, and through the resource dictionary when a picture names its space rather than writing it out. Where it cannot decide it does not decide quietly. A name is unique within one resource dictionary and not across the several a page reaches, so a page whose two forms each name their own Im1 marks both when either is CalRGB. That over-counts converted by at most those pictures; the other direction credits a colour conversion to a codec, which is what this is about. Bucket.Calibrated and the record's "calibrated" say how many pictures the second half of the rule moved, per filter and per bucket, because a rule that changes a bucket has to be able to say what it changed. On the four documents issue #20 names, it moves 4 of their 5 DCTDecode pictures and leaves the fifth where it was. Closes #20
v0.21.0 puts a JPEG's chroma back the way every other reader does: Go's image/jpeg replicates a subsampled chroma sample and libjpeg interpolates, and render now reproduces libjpeg's filter. That changes the decoded output of every subsampled JPEG in both corpora, so the records under baseline/ describe a library that no longer exists and the whole run is retaken. github.com/go-gfx/gfx also moved from v0.16.0 to v0.19.0 since those records were taken. Every record carries its own modules block; the prose beside them names the versions, and no table mixes two.
Every one of the 23 populations was re-run with the landed instrument at render v0.21.0, gate 2, the colour-space rule of #20 and the bound of #21. All 23 exited 0 and every one is in the tables. The improvement was being quoted as 61.2% to 99.3% corpus-wide. That figure is DCTDecode alone, at a gate of 4, over the 559 pictures pdfimages -list calls gray or rgb — a denominator #20 showed admits CalRGB, so it no longer exists here. At gate 2 across all 23 populations, DCTDecode goes 34.0% to 43.2% and the fleet 84.5% to 85.5%. That understates what happened, because the gate is a cliff and the change was a change of magnitude. The per-population medians of the worst channel on the direct DCTDecode rows were 16 18 23 23 26 31 34 47 50 58 62 171 244 255; they are now 3 3 3 3 3 3 4 4 4 4 171 233 255, and uk-govuk's row is gone entirely at 100.0%. Ten of thirteen rows sit one or two levels above the gate. Three did not move and are not chroma reconstruction. The previous run's finding that the empty band was gone, and that what sat under 1% was worse than what used to, was true of v0.20.0 and is not true of v0.21.0: ten of twenty direct rows are under 1% with a gap of 64.5 above them, and their peak medians are 3 and 4 rather than 18 and 23. It does not put the 1% back and nothing here proposes to — with N at 0 the criterion is the peak, so a band in the share is evidence about D, and it is recorded rather than spent. The colour-space rule moved five pictures, measurable exactly because the per-filter picture and unmatched counts are identical across the two runs: four DCTDecode and one (samples), and the four are the four #20 named. calibrated is 1802 and is a different quantity, which the document now says. And the only filter that moved is the only one the change touched: every other filter's agreement and the fleet's 1990 identical are unchanged to the picture.
The sections quoting the landed record were quoting v0.20.0, including the DCTDecode rate, the band analysis and the claim that what sat under 1% was worse than what used to. All three are properties of a library that no longer exists. What replaces them names the version, corrects the 61.2%-to-99.3% figure to what the landed instrument measures, and says why the rate understates a change that was one of magnitude.
tannevaled
force-pushed
the
baseline-render-v0.21.0
branch
from
August 31, 2026 17:45
119214b to
a6ca43d
Compare
Three precision defects in the prose, all of the kind that produced the figure this run exists to correct. The two ordered lists of peak medians are sorted, not paired, and have 14 and 13 rows; a reader pairing their columns gets the wrong population every time. They are now given paired as well. "Three did not move at all" was wrong about gh-pypdf, which went 244 to 233. It moved, just not to anywhere near rounding. And the whole-fleet figure spans three changes, not one: the denominators differ by the five pictures #20 moved, and gfx went v0.16.0 to v0.19.0 in between. All five moved pictures differ at v0.21.0, so the bucketing can be held fixed arithmetically: DCTDecode 42.8% and the fleet 85.4% are what is attributable to the library. Quoting 43.2% as v0.21.0's would credit a bucketing change to a library change, which is a smaller version of the same error.
Contributor
Author
|
Rebased onto Three precision defects in this PR's own prose are fixed in
The cleanest single number attributable to |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
renderv0.21.0 changes the decoded output of every subsampled JPEG in the fleet — Go'simage/jpegreplicates a subsampled chroma sample where libjpeg interpolates, and v0.21.0 reproduces libjpeg's filter. The landed records were taken at v0.20.0, so they described a library that no longer exists.All 23 populations, 3280 documents, re-run with the landed instrument. All 23 exited 0; each is committed on its own so an interruption cost one population rather than the run. Based on #22 and #23; it targets
mainbecause CI here isbranches: [main], so a PR pointing anywhere else reports no checks at all. Its diff shrinks to thebaseline:commits and the two READMEs once those land.The claim is corrected
The improvement was being quoted as 61.2% → 99.3% corpus-wide. That figure is not reproducible from the landed instrument, and it is not a corpus-wide figure: it is
DCTDecodealone, at a gate of 4, over the 559 picturespdfimages -listcallsgrayorrgb— a denominator #20 showed admits/CalRGB.At the landed gate of 2, over all 23 populations:
DCTDecodeagreementThe rate understates it, because the gate is a cliff and the change was one of magnitude. Per-population medians of the worst channel on the direct
DCTDecoderows:Ten of thirteen rows now sit one or two levels above the gate, where eleven of fourteen used to sit between 16 and 62. The row that vanished is
uk-govuk: 11 differing pictures to none, 92.3% → 100.0%. Three did not move —fr-impots255,gh-pypdf233,gh-qpdf171 — and those are not chroma reconstruction.Four other things the run says
The only filter that moved is the only filter the change touched.
(samples)69.7%,(samples) mask96.2%,JPXDecode99.2% and the three lossless filters at 100.0% are unchanged to the picture, as is the fleet's 1990 bit-identical. That is a check on the instrument as much as on the library.The previous run's argument about the empty band did not survive its own library. It found 2 of 21 direct rows under 1% with peak medians of 18 and 23 — "sparse gross error". At v0.21.0 it is 10 of 20 under 1%, a gap of 64.5 above them, and their peak medians are 3 and 4. It does not put the withdrawn 1% back and nothing here proposes to: with
Nat 0 the criterion is the peak, so a band in the share is evidence aboutD. Recorded, not spent.#20's rule moved exactly five pictures, and it is measured rather than asserted. The per-filter
picturesandunmatchedcounts are identical filter for filter across the two runs, so every difference in the direct/converted split is that rule:fr-cerfa3,gh-openpdf1,ia-uscourts1. Four areDCTDecode— the four/CalRGBpictures the issue named.calibrated, at 1802, is a different quantity, and the documentation that called it "what the rule moved" is corrected in this stack.hungis 0 everywhere, and the baseline says why that is not "nothing hangs". The document that hangs draws no picture on its first page, soimagesnever asks poppler about it;comparemeets it and names it. The bound is unexercised byimageson this corpus, and that is stated rather than left to be inferred.Two things held to, both learned here
No table mixes instruments or library versions. Every record carries its
modulesblock; the prose names v0.21.0, gate 2, the 2m0s bound andgfxv0.19.0, and the v0.20.0 figures appear only labelled as the previous run's.A population that did not complete would be named in the table with its reason. None was: all 23 completed, with peak memory
ia-americana5.9 GB,ia-biodiversity3.6 GB,ia-medical3.2 GB. Therefusedcount is 4, the same fouria-biodiversitydocuments, and they arerender's own 256-megapixel budget rather than documents we cannot read.No timings. Another job shared the machine throughout, so every duration measured would have measured that job as much as this one. Peak memory is reported because it is not a timing.
Gate
gofmt,go vet,-race, exact 100% statement coverage and the nine cross-compile targets, all underGOTOOLCHAIN=go1.27.0,GOWORK=off,CGO_ENABLED=0.