Repository navigation
Conversation
… (exploratory, LLM-generated) Addresses linebender#1147. An image drawn several times through <use> was loaded again by usvg for every instance (data URL decoded again, file read again, nested SVG parsed again), so each instance got its own data buffer, and resvg then decoded each instance again. usvg: the resolved `xlink:href` of `image` and `feImage` elements is cached in `converter::Cache`, keyed by the href string, so all instances of an image share the same `Arc` data. resvg: `render::Context` gets a cache of decoded raster images, keyed by the data pointer. An image is kept decoded only when its data has more than one owner (`Arc::strong_count > 1`), so images drawn once use no more memory than before. Tests ----- - All 1731 integration tests and the usvg tests pass, unchanged. - New usvg tests check that every <use> instance of an image, and every image with the same href, gets the same Arc data (both fail on main), and that an image used once has no other owner once parsing is done (resvg relies on this to decide which decoded images to keep). - Builds with and without the `raster-images` feature, `cargo fmt --check` is clean. Clippy not run. - Output is byte-identical to `main` on every file below. Benchmarks ---------- resvg CLI, release build, Linux x86_64, best of 5 runs, peak RSS from wait4(2). One 4000x3000 JPEG (1.5 MB) embedded as a data URL: | File | main | this commit | |----------------------|-----------------|-----------------| | drawn once | 59 ms, 55 MB | 58 ms, 55 MB | | drawn 10x via <use> | 509 ms, 69 MB | 67 ms, 55 MB | | drawn 30x via <use> | 1517 ms, 100 MB | 93 ms, 56 MB | | 10 distinct JPEGs | 590 ms, 87 MB | 596 ms, 86 MB | The usvg change alone only saves the data URL decoding (30x: about 1.5 s -> 1.4 s on a noisier run); most of the gain comes from resvg decoding once. Assumptions: a custom `ImageHrefResolver` returns the same result for the same href during one parse; if an API user holds an extra clone of an image's data, an image drawn once is also kept decoded for the render (memory only, not correctness). Disclosure: this change was written end to end by an LLM (Claude), as an exploration. It is published as inspiration only, not as a contribution, per the Linebender LLM contribution policy.
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.
Addresses #1147.
An image drawn several times through was loaded again by usvg for every instance (data URL decoded again, file read again, nested SVG parsed again), so each instance got its own data buffer, and resvg then decoded each instance again.
usvg: the resolved
xlink:hrefofimageandfeImageelements is cached inconverter::Cache, keyed by the href string, so all instances of an image share the sameArcdata.resvg:
render::Contextgets a cache of decoded raster images, keyed by the data pointer. An image is kept decoded only when its data has more than one owner (Arc::strong_count > 1), so images drawn once use no more memory than before.Tests
mainon every file below.Benchmarks
resvg CLI, release build, Linux x86_64, best of 5 runs, peak RSS from wait4(2). One 4000x3000 JPEG (1.5 MB) embedded as a data URL:
The usvg change alone only saves the data URL decoding (30x: about 1.5 s -> 1.4 s on a noisier run); most of the gain comes from resvg decoding once.
Disclosure: sorry but this change was written end to end by an LLM (Claude opus 5.5).