Skip to content
Redlamp

Performance

How fast Redlamp is, measured

Redlamp is built to answer every slider within a frame. These are its measurements over time, on an Apple M1 Ultra with a Release build: the figures the README recorded as the work landed, and the runs its benchmark harness records now. A metric counts as faster or slower only when it moves by more than 10%, or by more than its runs' own spread.

Open a raw fileFrom the README, 29 Sept 2026
70–250 ms
Render at Fit while editingFrom the README, 29 Sept 2026
0.6–3 ms
Render the whole photo at 1:1From the README, 29 Sept 2026
13 ms
Full-resolution export renderFrom the README, 29 Sept 2026
45 ms
Slowest 5% of iterations while draggingFrom the README, 30 Sept 2026
5 ms
All 50,000 photos listedFrom the README, 2 Oct 2026, under load
209 ms

Against a display's frame

What a slider costs while you drag it, and the whole photo at 1:1, beside one frame of a 120 Hz and a 60 Hz display.

Render at Fit with two gradient masks1.3 ms
Render at Fit while editing1.8 ms
Dragging sharpening's Amount at 1:12.2 ms
Dragging noise reduction's Luminance at 1:14.3 ms
Dragging sharpening's Radius at 1:15.5 ms
Default sharpening for a 1:1 view, first render7.2 ms
Render the whole photo at 1:113 ms
The lines mark one display frame at 120 Hz (8.3 ms) and at 60 Hz (16.7 ms); bars past the first are warm-coloured.

What's moved since it was first measured

Each metric's latest figure against its first, from the same source on the same machine. Some work makes a step slower on purpose, for better results; the change that did it is named beside each.

Getting faster

  • Slowest 5% of iterations while dragging97% faster

    157 ms on 30 Sept 2026, 5 ms on 30 Sept 2026

    1d243f3 Port the histogram and Tone Curve panel to AppKit

  • Detail stage GPU memory, 60 MP at 1:169% less

    7.5 GB on 4 Oct 2026, 2.3 GB on 4 Oct 2026

    5bf4dc9 README and tracker: detail-stage memory bounded (AUD-03, #160)

  • Main thread busy while dragging a slider66% faster

    100% on 30 Sept 2026, 34% on 30 Sept 2026

    1d243f3 Port the histogram and Tone Curve panel to AppKit

  • Detail stage GPU memory, 24 MP at 1:158% less

    3.1 GB on 4 Oct 2026, 1.3 GB on 4 Oct 2026

    5bf4dc9 README and tracker: detail-stage memory bounded (AUD-03, #160)

  • Default sharpening for a 1:1 view, first render15% faster

    8.5 ms on 30 Sept 2026, 7.2 ms on 30 Sept 2026

    0bf07c0 Faster Radius drags: precomputed blur weights, half-float deconvolution

Getting slower

  • Noise reduction for a 1:1 view89% slower

    1.9 ms on 30 Sept 2026, 3.6 ms on 2 Oct 2026

    205afb5 Non-local means for luma at 1:1 and in exports

  • Dragging noise reduction's Luminance at 1:154% slower

    2.8 ms on 2 Oct 2026, 4.3 ms on 2 Oct 2026

    205afb5 Non-local means for luma at 1:1 and in exports

Every metric over time

  • As recorded in the README
  • A harness run
  • Measured under load (drawn, never compared)
  • A range: the README's, or the fastest to slowest sample file

Opening

Open a raw file

Decode, GPU upload, demosaic and pyramid, for a 24–26 MP raw

70–250 ms

0 ms458 ms916 ms29 Sept4 Oct70–250 ms · 29 September 2026 · 04bf29a Redlamp iteration 1: native RAW editor for macOS · as recorded in the README392–796 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 29 Sept 2026.

Editing

Render at Fit while editing

Every adjustment in one fused pass, at a 2560 × 1600 view

0.6–3 ms

0 ms1.83 ms3.67 ms29 Sept4 Oct0.6–3 ms · 29 September 2026 · 04bf29a Redlamp iteration 1: native RAW editor for macOS · as recorded in the README1.7–3.2 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 29 Sept 2026.

Render at Fit with two gradient masks

A linear and a radial mask, each with local adjustments

1.3 ms

0 ms2.42 ms4.84 ms29 Sept4 Oct1.3 ms · 29 September 2026 · dbb6b5b Add gradient masking, Lightroom keyboard shortcuts, floating panels and CI · as recorded in the README2.3–4.2 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 29 Sept 2026.

Render the whole photo at 1:1

The full frame at full resolution, as when zoomed in

13 ms

0 ms7.48 ms15 ms29 Sept4 Oct13 ms · 29 September 2026 · 04bf29a Redlamp iteration 1: native RAW editor for macOS · as recorded in the README5.6–11 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 29 Sept 2026.

Export

Full-resolution export render

Developed at full resolution, read back for encoding

45 ms

0 ms72.8 ms146 ms29 Sept4 Oct45 ms · 29 September 2026 · 04bf29a Redlamp iteration 1: native RAW editor for macOS · as recorded in the README52.8–127 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 29 Sept 2026.

Full-resolution export with noise reduction

Luminance 50, rendered in tiles

100 ms

0 ms84.7 ms169 ms30 Sept4 Oct100 ms · 30 September 2026 · b10832c Noise reduction v1 behind the Detail panel's noise sliders · as recorded in the README61.1–147 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 30 Sept 2026.

Detail

Detail stage at 1:1: noise reduction

GPU time on a 1:1 region of about 10 MP of pyramid texels

5 ms

One measurement so far.

From the README, 30 Sept 2026.

Detail stage at 1:1: Texture and Clarity

GPU time on the same region

1 ms

One measurement so far.

From the README, 30 Sept 2026.

Noise reduction for a 1:1 view

GPU time, Luminance 50, a 2560 × 1600 view of a 24 MP photo

3.6 ms

0 ms2.07 ms4.14 ms30 Sept2 Oct1.9 ms · 30 September 2026 · 10fdfa2 Noise-aware capture sharpening · as recorded in the README2.7 ms · 2 October 2026 · f742a83 Keep luma texture in noise reduction with local-energy shrinkage · as recorded in the README3.6 ms · 2 October 2026 · 205afb5 Non-local means for luma at 1:1 and in exports · as recorded in the README

From the README, 2 Oct 2026; 33% slower than the record before.

Default sharpening for a 1:1 view, first render

GPU time, the same view

7.2 ms

0 ms4.89 ms9.77 ms30 Sept30 Sept8.5 ms · 30 September 2026 · 10fdfa2 Noise-aware capture sharpening · as recorded in the README7.2 ms · 30 September 2026 · 0bf07c0 Faster Radius drags: precomputed blur weights, half-float deconvolution · as recorded in the README

From the README, 30 Sept 2026; 15% faster than the record before.

Dragging sharpening's Radius at 1:1

GPU time per frame, the same view

5.5 ms

One measurement so far.

From the README, 30 Sept 2026.

Dragging sharpening's Amount at 1:1

GPU time per frame, with the analysis cached

2.2 ms

0 ms1.32 ms2.64 ms30 Sept30 Sept2.3 ms · 30 September 2026 · 10fdfa2 Noise-aware capture sharpening · as recorded in the README2.2 ms · 30 September 2026 · 0bf07c0 Faster Radius drags: precomputed blur weights, half-float deconvolution · as recorded in the README

From the README, 30 Sept 2026.

Dragging noise reduction's Luminance at 1:1

GPU time per frame, the same view

4.3 ms

0 ms2.47 ms4.94 ms2 Oct2 Oct2.8 ms · 2 October 2026 · f742a83 Keep luma texture in noise reduction with local-energy shrinkage · as recorded in the README4.3 ms · 2 October 2026 · 205afb5 Non-local means for luma at 1:1 and in exports · as recorded in the README

From the README, 2 Oct 2026; 54% slower than the record before.

Focus stacking

Focus stack of 25 Canon CR3 frames

17 MP frames: decode, align, depth map and fusion

8 s

One measurement so far.

From the README, 30 Sept 2026.

Focus stack of 109 JPEG frames

4 MP frames

15 s

One measurement so far.

From the README, 30 Sept 2026.

Reopen a merged focus stack

From its cache

0.1 s

One measurement so far.

From the README, 30 Sept 2026.

Memory

Detail stage GPU memory, 24 MP at 1:1

With noise reduction and sharpening on

1.3 GB

0 GB1.78 GB3.57 GB4 Oct4 Oct3.1 GB · 4 October 2026 · ec098fd Detail stage: scratch within budget on reuse, failed buffers forgotten (AUD-03, #160) · as recorded in the README1.3 GB · 4 October 2026 · 5bf4dc9 README and tracker: detail-stage memory bounded (AUD-03, #160) · as recorded in the README

From the README, 4 Oct 2026; 58% less than the record before.

Detail stage GPU memory, 60 MP at 1:1

With noise reduction and sharpening on

2.3 GB

0 GB4.31 GB8.63 GB4 Oct4 Oct7.5 GB · 4 October 2026 · ec098fd Detail stage: scratch within budget on reuse, failed buffers forgotten (AUD-03, #160) · as recorded in the README2.3 GB · 4 October 2026 · 5bf4dc9 README and tracker: detail-stage memory bounded (AUD-03, #160) · as recorded in the README

From the README, 4 Oct 2026; 69% less than the record before.

Peak memory browsing 50,000 photos

The app's footprint while listing, decoding and warming thumbnails

317 MB

0 MB305 MB611 MB2 Oct2 Oct457 MB · 2 October 2026 · c04795f Folders: README, research tracker and design results · as recorded in the README, measured under load531 MB · 2 October 2026 · b957362 Thumbnails: raw files decode their smallest fitting embedded preview, found by LibRaw · as recorded in the README, measured under load317 MB · 2 October 2026 · ddf161f Folders: memory budgets, how the footprint is attributed, and what the measurements changed · as recorded in the README, measured under load

From the README, 2 Oct 2026, under load.

Folders

First photos in the filmstrip

50,000 photos in 500 folders, Show Photos in Subfolders on

14 ms

One measurement so far.

From the README, 2 Oct 2026, under load.

All 50,000 photos listed

500 folders, in parallel, in order

209 ms

One measurement so far.

From the README, 2 Oct 2026, under load.

Visible thumbnails from the raw files

The first screenful, decoded from the files

33 ms

0 ms113 ms227 ms2 Oct2 Oct197 ms · 2 October 2026 · c04795f Folders: README, research tracker and design results · as recorded in the README, measured under load33 ms · 2 October 2026 · b957362 Thumbnails: raw files decode their smallest fitting embedded preview, found by LibRaw · as recorded in the README, measured under load

From the README, 2 Oct 2026, under load.

Thumbnails warmed from the raw files

In the background, while you're not waiting

705 a second

04058112 Oct2 Oct253 a second · 2 October 2026 · c04795f Folders: README, research tracker and design results · as recorded in the README, measured under load705 a second · 2 October 2026 · b957362 Thumbnails: raw files decode their smallest fitting embedded preview, found by LibRaw · as recorded in the README, measured under load

From the README, 2 Oct 2026, under load.

Thumbnails from the disk cache

Read back from the per-folder cache

6,210 a second

One measurement so far.

From the README, 2 Oct 2026, under load.

Responsiveness

Main thread while listing and warming (p99)

The slowest 1% of run-loop iterations

0.15 ms

One measurement so far.

From the README, 2 Oct 2026, under load.

Main thread scrolling the filmstrip (p99)

End to end at 120 Hz

1.4 ms

One measurement so far.

From the README, 2 Oct 2026, under load.

Main thread busy while dragging a slider

120 events a second, every panel open

34%

0%57.5%115%30 Sept4 Oct100% · 30 September 2026 · 79b0a75 Ignore Python bytecode · as recorded in the README54% · 30 September 2026 · 675dd8f Keep slider drags off the main thread · as recorded in the README36%–41% · 30 September 2026 · 0d20a7e Port the Basic panel to AppKit and add a component harness · as recorded in the README34% · 30 September 2026 · 1d243f3 Port the histogram and Tone Curve panel to AppKit · as recorded in the README63% · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 30 Sept 2026.

Typical run-loop iteration while dragging

The median

0.17 ms

0 ms0.56 ms1.12 ms30 Sept4 Oct0.16–0.19 ms · 30 September 2026 · 0d20a7e Port the Basic panel to AppKit and add a component harness · as recorded in the README0.17 ms · 30 September 2026 · 1d243f3 Port the histogram and Tone Curve panel to AppKit · as recorded in the README0.98 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 30 Sept 2026.

Slowest 5% of iterations while dragging

The 95th percentile

5 ms

0 ms90.3 ms181 ms30 Sept4 Oct157 ms · 30 September 2026 · 79b0a75 Ignore Python bytecode · as recorded in the README8 ms · 30 September 2026 · 675dd8f Keep slider drags off the main thread · as recorded in the README6 ms · 30 September 2026 · 0d20a7e Port the Basic panel to AppKit and add a component harness · as recorded in the README5 ms · 30 September 2026 · 1d243f3 Port the histogram and Tone Curve panel to AppKit · as recorded in the README5.3 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 30 Sept 2026.

Slowest 1% of iterations while dragging

The 99th percentile

8 ms

0 ms4.6 ms9.2 ms30 Sept4 Oct8 ms · 30 September 2026 · 1d243f3 Port the histogram and Tone Curve panel to AppKit · as recorded in the README6.7 ms · 4 October 2026 · a010ea1 Hero shots: the Masks shot shows a Subject mask on the dancer in the red overlay, with its own Exposure and Clarity · harness run, measured under load

From the README, 30 Sept 2026.

How it's measured

  • scripts/perf-record.sh builds Release and runs redlamp bench on the CC0 sample raws from raw.pixls.us (each measurement repeated after a warm-up; a metric is the median across the files), then drags a slider at 120 events a second with every panel open, and opens 50,000 photos in 500 folders.
  • Runs recorded while the Mac was busy (a load average above 8) are kept and drawn but never compared, and the figures the README recorded (19 versions from 29 September) are compared only with each other: they were measured by hand, some as ranges.
  • The latest harness run: 4 October 2026, commit a010ea1, Apple M1 Ultra with 128 GB, macOS 26.6.2, 7 runs per measurement, load average 27.17 before and 49.94 after, so it's recorded as noisy.
  • No Lightroom figures: Redlamp hasn't measured Lightroom on the same photos.

Read from docs/performance/history.jsonl at commit 95a532f.