Skip to content

[performance] Single-lookup SKRuntimeEffectUniforms.Add - #4811

Draft
github-actions[bot] wants to merge 1 commit into
mainfrom
dev/perf-runtimeeffect-uniforms-add-6327e9a55f916ab0
Draft

[performance] Single-lookup SKRuntimeEffectUniforms.Add#4811
github-actions[bot] wants to merge 1 commit into
mainfrom
dev/perf-runtimeeffect-uniforms-add-6327e9a55f916ab0

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Description

SKRuntimeEffectUniforms.Add resolved every uniform name twice per call: an Array.IndexOf(names, name) O(n) linear scan (used only for the not-found check) followed by a redundant uniforms[name] hash lookup. The name -> Variable dictionary already answers both, so this replaces both with a single Dictionary.TryGetValue.

Animated runtime-effect shaders assign every uniform each frame via uniforms["name"] = value (which calls Add), so this is a real per-frame hot path whose cost grew with the uniform count.

Changes

  • binding/SkiaSharp/SKRuntimeEffect.cs: SKRuntimeEffectUniforms.Add now uses one TryGetValue instead of Array.IndexOf + indexer. Method-body-only change; the ArgumentOutOfRangeException type, param name and message for unknown names are unchanged. ABI-safe (no signature/API change).
  • benchmarks/SkiaSharp.Benchmarks/Benchmarks/SKRuntimeEffectUniformsAddBenchmark.cs: New-vs-Old BenchmarkDotNet benchmark mirroring Add's internals.
  • tests/Tests/SkiaSharp/SKRuntimeEffectTest.cs: AddResolvesUniformsIdenticallyAndRejectsUnknownNames equivalence regression test.

Required skia PR

None.

Areas Affected

  • SkiaSharp (SKRuntimeEffect / runtime-effect uniforms)

Testing

Benchmark (BenchmarkDotNet ShortRun, MemoryDiagnoser, net10.0 / x64 / Linux):

N (uniforms) Old New Ratio Allocations
8 1,304.0 ns 660.8 ns 0.51 none (both)
32 43,662.4 ns 10,553.3 ns 0.24 none (both)

~2x faster at 8 uniforms, ~4x at 32; no allocation change.

Equivalence test: AddResolvesUniformsIdenticallyAndRejectsUnknownNames verifies every declared name writes to the correct packed offset and that unknown names throw the same ArgumentOutOfRangeException (same param name + message). Confirmed it FAILS against a deliberately-wrong param name and PASSES on the fix. Full test run via the console host project on net10.0.

No rendering change (managed lookup only), so no before/after screenshots apply.

Fixes #4810


Produced by the performance-fixer agentic workflow using the performance-fixer skill. Numbers are empirically measured (not statically reasoned) on net10.0 / x64 / Linux via BenchmarkDotNet ShortRun; ratios are New/Old and are the portable result (absolute ns are machine-relative). Managed-only change, no ABI impact.

Generated by Fixer - Performance · opus48 · 557.9 AIC · ⌖ 35.6 AIC · ⊞ 13K ·

Replace the Array.IndexOf (O(n) linear scan) plus redundant dictionary
indexer in SKRuntimeEffectUniforms.Add with a single Dictionary.TryGetValue.
The name->Variable map already answers both the existence check and the
fetch, so the linear scan and the extra hash lookup are pure overhead on a
per-frame hot path (animated runtime-effect shaders set every uniform each
frame).

Behaviour is identical: valid names resolve to the same Variable/offset and
unknown names still throw ArgumentOutOfRangeException with the same param
name and message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added partner/agentic-workflows Issues and PRs created by SkiaSharp agentic workflows. perf/throughput Operation slower than expected: decode/encode, loading, conversion. Implies tenet/performance. tenet/performance Performance related issues labels Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

partner/agentic-workflows Issues and PRs created by SkiaSharp agentic workflows. perf/throughput Operation slower than expected: decode/encode, loading, conversion. Implies tenet/performance. tenet/performance Performance related issues

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

[performance] SKRuntimeEffectUniforms.Add resolves each uniform name twice (O(n) scan + redundant hash)

0 participants