Skip to main content
Known Participant
Nov 2, 2026 7:39 AM UTC
Question

Recomputing the hidden Optics panel's lens-profile menus blocks main thread 0.3s per photo in Details view

Description of Issue


- While culling in Detail view with the Edit panel hidden, each photo step spends about 0.3 s of main-thread CPU recomputing the Optics panel's lens-profile properties (lensProfileName, lensProfileMakes, lensProfileLensNames, lensProfileNames in AgCameraRawControllerLensCorrection.lua). In a 60-second recording that was 14.9 of the main thread's 26.3 CPU-seconds (57%).


- The expensive one is negative:getLensProfileName (the lensProfileName getter): about 94 ms per call (up to 115 ms), 3–4 calls per photo. Lightroom can't respond to input during each call.

 

- Why each call is slow: to name the photo's profile, Camera Raw classifies every lens profile by maker. For each profile it searches up to three name fields for each of 50 maker names ("Canon", "Nikon", "Sony", ... "REEFLEX") with a byte-by-byte case-insensitive substring search, after a series of mount tests ("Leica R", "Sony FE", "Zeiss ZE", ...). Lightroom ships 3,633 lens profile files. The classification never changes between calls.


- It happens for Canon R5 Mark II / R6 Mark III (RF lenses) and Sony A7R III (FE lenses) raw files, and almost not at all for Panasonic GH5 and iPhone photos. It doesn't happen in Grid view.


- Path (arm64 file offsets in CameraRaw, Lightroom 9.6 build 20260923-1659-a32d844): main run loop → queued notification (postQueueNotifications) → AgSubstrate observer → lua_pcall → lensProfileName getter → negative:getLensProfileName binding (+0x76f88) → +0x4a6ad8 / +0x4a7000 → +0x4b1928 / +0x4b1a38 → loops over the profiles in +0x4af12c / +0x4af8e8 → maker classifier +0x496284 → case-insensitive substring search +0xe14274.


- Related: report 10 (https://community.adobe.com/bug-reports-679/detail-view-runs-a-transparent-area-check-on-every-photo-using-39-54-of-lightroom-s-cpu-while-culling-1653987) is another piece of work done on every photo for a panel that isn't on screen (the Crop panel's transparent-area check).

 

Step-by-step Reproduction Instructions


1. Launch Lightroom and open an album of raw photos from a camera and lens that Lightroom has a lens profile for (here Canon EOS R5 Mark II with RF lenses, or Sony A7R III with FE lenses). Select a photo and press D for Detail view. Leave the Edit panel closed.


2. With Xcode installed, in Terminal:
   xcrun xctrace record --template "Time Profiler" --attach $(pgrep -x "Adobe Lightroom") --time-limit 60s --output lr.trace
   Switch to Lightroom right away and press the Right arrow about once a second until the recording ends.


3. Open lr.trace in Instruments and select the Main Thread. In the Call Tree (Invert Call Tree), the heaviest frames are in CameraRaw, called from lua_pcall under the notification observer (postQueueNotifications). With symbols they're the getLensProfileName binding, the lens profile maker classifier and its case-insensitive substring search. In the thread's timeline each call is a solid 90–115 ms block, 3–4 per photo.


4. Repeat with G (Grid view) and the arrow keys: none of these frames appear.

 

The Expected Result


- The Optics panel's lens-profile name and menus are computed when that panel or the lens profile chooser is shown, not on every photo while the Edit panel is hidden.


- Looking up one profile's name doesn't classify every profile: the maker of each lens profile is worked out once when the profiles load (or the profiles are indexed by maker and name), so a lookup takes microseconds instead of ~94 ms.


- At most one lookup per photo, and none on the main thread (lagging user input) if it has to scan.

 

The Actual Result


- 2026-11-02 00:32 (UTC-6), 60.9 s Time Profiler, Detail view, Edit panel hidden, Canon R5 Mark II / R6 Mark III CR3 shoot, D then Left/Right about once a second (script), 44 photo steps:
  - Main thread: 26.3 CPU-seconds.
  - negative:getLensProfileName: 11.95 s in 165 calls (each unbroken run of samples with the binding on the main thread's stack), median 94 ms, 90th percentile 112 ms, max 115 ms: ~3.75 calls and ~0.27 s per photo step.
  - getLensProfileLensNames: 109 calls of ~10 ms (1.10 s). getLensProfileMakes: 109 of ~8 ms (0.93 s). getLensProfileNames: 109 of ~8 ms (0.87 s).
  - All four together: 14.9 s, 57% of the main thread's CPU, ~0.34 s per photo step.
  - The case-insensitive substring search alone: 13.3 s, 44% of the main thread's CPU.

 

- 2026-11-02 00:01, 30.8 s of normal manual culling, same shoot (~15 photo steps): getLensProfileName 43 calls, median 96 ms, 3.2 s.


- 2026-11-02 01:02, 90.9 s over other cameras' photos, with a per-photo log: getLensProfileName 110 calls, median 91 ms, 7.5 s; 0.21 s per Sony A7R III photo (36 photos shown), ~0.00 s per Panasonic GH5 (17) and iPhone (19) photo.


- 2026-11-02 01:13, 60.8 s, Grid view, same Canon shoot and script (G instead of D): no calls.

 

System Details


- Lightroom 9.6 (Mac App Store), build 20260923-1659-a32d844, arm64
- macOS 27.0.1 (26A434), MacBook Pro 16" (MacBookPro18,2), Apple M1 Max (10 cores), 64 GB RAM
- Library: 41,490 photos, 211 albums, 4,818 stacks; local library 78–85 GB (40 GB originals, 29 GB proxies, 12 GB previews); all proxies stored locally, photo cache limit 50 GB