Go to file
Greg Pomerantz a6b5e31924 Jank hunt: repro on emulator, rule out 6 causes, add A/B tooling
Findings (emulator programmatic-scroll repro, phone log data):
- In-place cell updates (cells.set_row_data) replaced whole-row
  replacement: no subtree teardown, texture upload only on pixel
  change. MAX_PAINT_CELLS_PER_TICK=2.
- Static placeholder replaces the animation-tick() shimmer: the per-cell
  sin() binding was O(all 8577 cells) every frame (71% CPU idle).
  O(visible) shimmer is M6 work.
- nblog: non-blocking logger (bounded mpsc + drain thread calling
  __android_log_write). logd backpressure was stalling the UI thread
  10-40 ms. android_logger dependency no longer used on-device.
- cpuload (SELinux-blocked) removed; min_refresh_rate=120 pin kills the
  SystemUI 60Hz flap (noted in HANDOFF, reversible).
- Emulator: during every 28-146 ms stall the UI thread is 100% on-CPU;
  capping the list to 300 items does NOT help (scene size is not the
  cost); grey 1x1 images cut 30-146 ms to a steady ~16.6 ms -> the
  cost is software-GL rasterization of ~30 textured cells at 1080x2400
  (emulator ceiling; the emulator validates logic, not feel).
- Phone 28-39 ms spikes are NOT first-paint/upload timing (they happen
  ~10x more often than cells enter the viewport) and not upload CPU
  cost (1.2-2.9 ms). Left: GPU/present contention vs Slint EGL path.

Tooling (all tagged REMOVE after the hunt, file-gated, off by default):
- .gallery_cmd scroll hook + SCRDBG/TICK/APLY logs
- .gallery_max (item cap) and .gallery_grey (1x1 images) A/B knobs
- HANDOFF 8.5: full findings + decisive phone A/B plan for tomorrow
- jsample.c (NDK /proc sampler, /tmp): per-thread state+wchan

Also: fix pre-existing doctest (indented module-doc block parsed as
Rust); 15 unit tests + doctest green; aarch64 release APK builds.
2026-10-28 00:43:35 -04:00
scripts M2: thumbnail engine — turbojpeg DCT-shrink decode, worker pool, disk cache 2026-10-27 16:32:12 -04:00
src Jank hunt: repro on emulator, rule out 6 causes, add A/B tooling 2026-10-28 00:43:35 -04:00
.gitignore M0: Slint gallery scaffold + development hand-off 2026-10-27 12:22:59 -04:00
build.rs M0: Slint gallery scaffold + development hand-off 2026-10-27 12:22:59 -04:00
Cargo.lock M2: thumbnail engine — turbojpeg DCT-shrink decode, worker pool, disk cache 2026-10-27 16:32:12 -04:00
Cargo.toml M2: thumbnail engine — turbojpeg DCT-shrink decode, worker pool, disk cache 2026-10-27 16:32:12 -04:00
HANDOFF.md Jank hunt: repro on emulator, rule out 6 causes, add A/B tooling 2026-10-28 00:43:35 -04:00
LICENSE Initial commit 2026-10-27 12:13:22 -04:00
README.md M1: metadata scan + sqlite DB + placeholder list 2026-10-27 13:28:33 -04:00

gallery

A high-performance image gallery for Android (primary), Linux and macOS — Rust + Slint 1.18.

Status: M1 (metadata scan + DB) done. See HANDOFF.md — the development hand-off with the full plan: architecture, thumbnail pipeline, milestones M1–M7, Slint gotchas, permission flow, and performance targets. Next: M2 (thumbnail engine).

Build

./scripts/build.sh debug     # debug x86_64 APK + install on emulator
./scripts/build.sh           # release x86_64 (emulator)
./scripts/build.sh aarch64   # release aarch64 (device)
cargo run                    # desktop (Linux needs libfontconfig1 + pkg-config)

Requires: Rust (rustup), cargo-apk2, Android SDK + NDK 27 (see HANDOFF.md §3 for exact paths/env).

License

GPL-3.0 (see LICENSE). Built on Slint, used under the Slint royalty-free license for proprietary apps (see HANDOFF.md §10.4).