The load and refresh cost of an SVG is not one number. In Svg.Skia the work is split across document parsing, retained-scene compilation, shim-model creation, native SKPicture materialization, and any later raster export.
This matters when a device looks "slow to load" because the bottleneck may be DOM parsing, scene compilation, PNG encoding, or a full rebuild after a small mutation.
The benchmark project includes a dedicated profiler for one SVG file:
dotnet run --project tests/Svg.Skia.Benchmarks/Svg.Skia.Benchmarks.csproj -c Release -- --profile-svg '/Users/wieslawsoltes/Downloads/solar battery.svg' 20
That command reports separate timings for:
SvgDocument,SvgSceneDocument,SKPicture model,SkiaSharp.SKPicture,SKSvg.FromSvg(...),FromSvgDocument(...) rebuild after a mutation,Example output from osx-arm64, Release, 20 iterations, for /Users/wieslawsoltes/Downloads/solar battery.svg (29,974 bytes):
| Stage | Mean |
|---|---|
Parse SvgDocument from string |
2.46 ms |
| Compile retained scene | 5.08 ms |
| Create shim picture model | 0.04 ms |
Create native SKPicture |
0.53 ms |
| Render native picture to bitmap | 3.77 ms |
| Encode native picture to PNG | 13.85 ms |
Load via SKSvg.FromSvg(...) |
12.39 ms |
| Control-like source load | 11.14 ms |
Mutate + full FromSvgDocument(...) rebuild |
16.11 ms |
| Mutate + retained-scene refresh | 12.73 ms |
Treat those numbers as a shape, not a promise. CM4, CM5, desktop ARM, and different output resolutions will change the absolute timings.
The staged profile above points at the current hot paths:
SKSvg,FromSvgDocument(...) rebuild for small localized edits.Text-heavy documents can push more cost into text compilation and measurement than purely geometric assets, so profile representative files instead of relying on one benchmark.
SKSvg exposes three refresh helpers for localized DOM edits:
TryApplyRetainedSceneMutationAndRender(SvgElement element, IReadOnlyCollection<string>? changedAttributes, out SvgSceneMutationResult? result)TryApplyRetainedSceneMutationAndRender(string addressKey, IReadOnlyCollection<string>? changedAttributes, out SvgSceneMutationResult? result)TryApplyRetainedSceneMutationByIdAndRender(string id, IReadOnlyCollection<string>? changedAttributes, out SvgSceneMutationResult? result)Example:
using System.Drawing;
using Svg;
using Svg.Skia;
using var svg = new SKSvg();
svg.FromSvg(
"<svg width=\"80\" height=\"40\">" +
" <rect id=\"rect-a\" x=\"10\" y=\"8\" width=\"24\" height=\"12\" fill=\"red\" />" +
"</svg>");
var scene = svg.RetainedSceneGraph!;
var rect = (SvgRectangle)scene.SourceDocument!.GetElementById("rect-a")!;
rect.Fill = new SvgColourServer(Color.BlueViolet);
if (!svg.TryApplyRetainedSceneMutationByIdAndRender("rect-a", new[] { "fill" }, out var result))
{
svg.FromSvgDocument(scene.SourceDocument);
}
The returned SvgSceneMutationResult reports whether the refresh succeeded and how many compilation roots had to be recompiled.
Use retained-scene refresh when:
Picture refreshed without a full DOM-to-scene recompilation.Use FromSvgDocument(...) when:
Use ReLoad(...) when:
SvgParameters changed,