Skip to content

ADFA-6810 | Log model load time; hint the kernel to read ahead on a selection's first load - #160

Open
davidschachterADFA wants to merge 4 commits into
mainfrom
ADFA-6810-local-model-load-fadvise
Open

davidschachterADFA wants to merge 4 commits into
mainfrom
ADFA-6810-local-model-load-fadvise

Conversation

@davidschachterADFA

@davidschachterADFA davidschachterADFA commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Logs model load wall time and MB/s around engine.load (Model load: <N> ms, <X> MB/s).
  • Adds posix_fadvise(WILLNEED) from the JNI wrapper before the model is mapped, on the first load after the app starts or the selection changes. A reload of the same selection skips it. The code remembers one selection, so switching A to B and back to A hints A again.
  • Adds standalone cold-cache measurement tooling (scripts/evict_cache.c, scripts/evict-page-cache.sh); not part of the plugin build.
  • Rebuilds the AAR from the pinned llama.cpp c9058a713 (wrapper change only, no fork change).

Honest measurement caveat

Non-interleaved runs showed ~31% off a cold FUSE load, but an interleaved on/off test (n=5/n=4) found no reliable cold difference (2748 vs 2693 ms, stdev ~400). A warm load through FUSE seemed ~140 ms slower with the hint (cross-session, not re-checked interleaved). Shipped on the judgement that it can save time on a cold load and rarely costs a little. The main finding on the ticket is that storage location dominates: FUSE cold is ~4.2x warm, private storage ~1.5x.

Review

An independent review (Opus) found no blockers. Its one should-fix, a test that a load refused before the engine does not consume the hint, is added (and shown to fail if the hint is armed too early). Wording, timing-log, O_CLOEXEC and eviction-script nits are fixed in the second commit.

Test plan

  • testDebugUnitTest passes, including the new first-load/reload/different-selection test and the AAR source-stamp test
  • assemblePluginDebug builds; installed and loaded on a Pixel 6 Pro
  • Steps to QA (Gherkin) attached to ADFA-6810
  • Warm load on the final gated build and other devices/larger models not measured

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vh2DAYJVrBKjeghKxnig7N

davidschachterADFA and others added 2 commits October 30, 2026 22:19
…ooling for repeatable cold-load measurement

Logs load duration and MB/s on every model load, giving Phase 1's cold/warm
comparison a real signal instead of guessing whether load time is I/O-bound.

evict_cache.c/evict-page-cache.sh are standalone measurement aids (not built
into the plugin) that force a file's clean pages out of the page cache via
posix_fadvise(DONTNEED), so a cold model load can be repeated on a private-
storage (f2fs) file without root or a reboot. They have no effect through
FUSE (/sdcard); a reboot is still required there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vh2DAYJVrBKjeghKxnig7N
…l load

Issues posix_fadvise(WILLNEED) from the JNI wrapper before the model is
mapped, only on the first load of a selection in a process (the load most
likely to be cold). Reloads of the same selection skip it.

Measurement caveat: non-interleaved runs showed ~31% off a cold FUSE load,
but an interleaved on/off test showed no reliable difference. A warm load
through FUSE seemed to cost ~140 ms more with the hint. Shipped on the
judgement that it can save time on a cold load and rarely costs a little.

Needs no llama.cpp fork change; AAR rebuilt from the pinned c9058a713.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vh2DAYJVrBKjeghKxnig7N
davidschachterADFA and others added 2 commits October 31, 2026 01:51
- Test that a load refused before the engine does not consume the hint;
  checked it fails if the hint is armed above the refusals.
- Document that the hint tracks one selection (A, B, A re-hints A), and
  correct comments that overstated the benefit or said "concurrently".
- Timing log: say it covers the whole engine.load, format MB/s with
  Locale.ROOT, and skip it for a zero-byte size.
- Open the hint's descriptor with O_CLOEXEC.
- Eviction tooling: report "advised DONTNEED" instead of "evicted", quote
  device paths with spaces, and give the missing-NDK message.

AAR rebuilt for the C++ change; source stamp matches.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vh2DAYJVrBKjeghKxnig7N
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