Skip to content

perf: cache sRGB and Display P3 transfer values - #23

Open
2dubu wants to merge 1 commit into
mainfrom
perf/color-transfer-lut
Open

2dubu wants to merge 1 commit into
mainfrom
perf/color-transfer-lut

Conversation

@2dubu

@2dubu 2dubu commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Summary

Cache the 256 sRGB/Display P3 transfer-function values so RGB-to-OKLCH conversion reuses them instead of evaluating the same power function for every pixel channel.

Background

Both input transfer functions accept UInt8 and use the same formula. Repeated image extraction therefore recomputes one of only 256 possible Double values for each channel. The default OKLCH extraction path pays this cost across all sampled pixels.

Solution

Build one private, immutable table using the existing formula and index it from both transfer functions. Matrix operations, inverse conversion, precision, sampling, and public APIs stay the same. Swift initializes the table once on first use; its element storage is approximately 2 KiB.

Related Issue

N/A.

Verification

  • Added exhaustive 8-bit channel tests against an independent implementation of the original formula: sRGB and P3 Double.bitPattern equality and all-channel round trips. The same tests pass on the unmodified base.
  • Added deterministic, opt-in sRGB/P3 batch conversion benchmarks with input generation and warmup outside measurement, and output consumed after measurement.
  • Commands run:
    • swift package resolve
    • swift build -c debug
    • swift test --filter OKLCHConversionTests — 2 tests passed.
    • swift test --filter PaletteKitTests --filter PaletteKitInsightsTests — 61 tests passed.
    • swift test -c release --filter OKLCHConversionTests — 2 tests passed.
    • swift test -c release --skip-build --filter OKLCHConversionBenchmarks — 2 benchmarks passed in each comparison run.
    • git diff --check
  • Environment: Apple M5 Max, macOS 26.6.2, Swift 6.3.2. These are native Mac results, not iPhone performance measurements. iOS Simulator compatibility is checked by the PR workflow.

Compatibility and Impact

  • Public API: None.
  • Behavioral impact: Intended color values and extraction behavior are unchanged; every possible input channel matches the original transfer calculation on the tested toolchain.
  • Performance impact: Lower steady-state conversion cost, with a one-time table initialization cost and approximately 2 KiB of persistent element storage. First-call latency is not measured by the warm benchmark.
  • Affected platforms: Shared code on iOS and macOS.

Additional Context

Release benchmark medians for 100,000 deterministic pseudo-random pixels; 15 XCTClockMetric samples per case from three process runs with baseline/candidate order alternated:

Conversion only Base 2286664 LUT Lower latency
sRGB to scaled OKLCH 6.141 ms 3.360 ms 45.3%
Display P3 to scaled OKLCH 6.385 ms 3.609 ms 43.5%

Run swift test -c release --filter OKLCHConversionBenchmarks to reproduce. For the baseline, use 2286664 with only the new benchmark file copied unchanged. These numbers cover conversion and output allocation; they exclude image decode, sampling, quantization, and first-use initialization. They do not establish a corresponding full-API or iPhone improvement percentage.

This branch is based directly on main and can be reviewed independently.

Checklist

  • This pull request is focused and contains no unrelated changes.
  • Tests were added or updated where behavior changed, or I explained why they are not needed.
  • Regression tests cover the intended behavior or root cause rather than only a reported sample.
  • Public API changes are documented and reflected in the changelog, or this pull request has none.
  • I considered source compatibility, behavioral changes, and performance impact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant