It finds the fastest local-LLM setup for your exact Arm chip. Then it proves it.
Android · arm64 · free and open source · Arm Create : AI Optimization Challenge 2026 · Mobile AI Track
Android phones run wildly different Arm silicon under the same OS: different matrix instructions, different core layouts, different memory bandwidth. Almost every local-LLM app ships one generic build and hopes for the best, which leaves most of the phone's speed unused.
PocketTune answers the one thing a spec sheet can't: what's actually fastest on the phone in your hand.
On-device LLM apps compile once, generically — using none of the SIMD instructions the chip actually has.
The chip with more matrix instructions should win. Measured on four phones, it doesn't: the biggest winner is missing the headline feature entirely.
Extra threads land on slow little cores and everyone waits for them. The right count differs per phone.
No public per-phone dataset says which config wins where — so every phone has to find out for itself.
These are the speed ranges across , each one measured against its own unoptimized baseline. The spread is the whole point: the same optimization is worth a different amount on different silicon, so no single number describes your phone. See the per-device evidence ›
One panel per device we've benchmarked. Same model, same workload — only the build changes.
Read each ladder top to bottom. The speedup shows up with the compiler flags, which are really just permission to use the matrix instructions the silicon already has. Which instructions exist, and what they're worth, is a property of the chip, not the app. That's the reason we measure instead of assume.
One build flag lets the compiler emit the SIMD instructions the chip already has, and most Android builds never pass it. How much it buys moves around unpredictably: 1.00×, 3.88×, 4.94×, 5.27× across four phones. It doesn't track the feature list either — the biggest winner has no i8mm at all, and on a chip below dotprod the flag buys nothing, because there's nothing for it to unlock.
Arm's own acceleration library, tested head-to-head: no measurable gain on the i8mm chip, and a measured −3.6% on the Pixel 7a. Plain compiled code already saturates this hardware for Q4_0, and llama.cpp's own repack path beats the kernels on Tensor G2. On other quants and other silicon it may well flip, which is why it stays in the sweep.
Four phones, four different optima, and no, it isn't “all of them” by default. The two big.LITTLE chips want 2; the tri-cluster Pixel wants 4, because it has exactly four fast cores, and asking it for 6 drops prefill from 143 to 102 tok/s. But the Snapdragon 710 really does want all 6: its big cores are weak enough that the little ones still add throughput. Even the direction of the rule flips from chip to chip.
Every one of these contradicts what a reasonable developer would assume, and none of them holds across chips by default. Which is the whole reason the app works the way it does: your phone's fastest configuration is a question you can only answer by measuring, so PocketTune measures it on your phone.
Which fast instructions does this chip have — dotprod? i8mm? How many fast versus slow cores? Read straight off the device.
Compression formats, instruction paths, thread counts — measured for speed, memory and energy per token, right on the phone.
The best configuration isn't a report. It becomes the app's live settings, chosen on evidence.
A private assistant running the tuned setup. Airplane mode is the demo — nothing leaves the phone.
Every line we wrote is TypeScript. Every fast path below it is measured, never assumed.
React Native, all TypeScript. Device reads the silicon, Models manages GGUF downloads, Tune runs the sweep and applies the winner, Chat runs it offline.
Builds the sweep plan from this phone's core layout, drives the benchmarks, scores every configuration (weighted 65% decode, 35% prefill), samples battery power for tokens per joule, and persists the applied config and history.
A prebuilt binding to the engine — no native code written in this project. It ships six arm64 kernel builds and picks one at startup by reading the chip's features: i8mm silicon gets the i8mm build, a dotprod-only chip gets the dotprod build.
Loads the GGUF model and runs the matmuls. One context lives at a time — a phone doesn't have RAM for two — and every engine call is serialized, so a mid-benchmark tab switch can never corrupt a measurement.
The ground truth: which matrix instructions exist (dotprod? i8mm? SVE2?) and where the big cores sit. Different on every phone — which is exactly why every layer above asks instead of assumes.
The whole stack exists to take one decision — which configuration to run — and settle it by measurement on the phone in your hand, rather than by guesswork.
Build-time levers are baked into the binaries and proved by the harness. Runtime levers are what the app tunes on your phone. Every one is measured, and two of the "obvious wins" turned out to be worth nothing.
-march=armv8.2-a+dotprod+i8mm gives the compiler permission to emit the chip's matrix-multiply instructions. Generic arm64 builds — what most apps ship — use none of them. This single flag is the largest gain in the entire project.
At model load, llama.cpp rearranges Q4_0 weight blocks into the tile order the i8mm instructions consume — so the SIMD units stream contiguous data instead of gathering it. Free at inference time; it costs a moment at load.
Arm's hand-written matmul routines — the thing everyone assumes brings the speed. Tested head-to-head on the i8mm chip: ≈0% once the compiler flags are right. On the Pixel 7a, isolating it against a KleidiAI-free control went further — KleidiAI costs ~3.6% there, because llama.cpp's own repack path beats the kernels for Q4_0. It stays in the sweep because other silicon and other quantizations may disagree.
Decode speed is bounded by memory traffic, not arithmetic — the CPU mostly waits for weights to arrive from RAM. Shrinking every weight from 16 bits to ~4 cuts that traffic roughly 4×, and is what makes a 1B-parameter model fit on a phone at all.
More threads is actually worse when the extra workers are little cores, because the whole team waits for the slowest. And the winning count is different on every phone: the two big.LITTLE chips want 2 threads, while the tri-cluster Pixel wants 4, because it has exactly four fast cores (2× X1 + 2× A78) and the 5th thread spills onto an A55. The app builds its candidates from this phone's actual core map instead of defaulting to "all of them".
Flash attention computes attention in cache-sized tiles instead of materializing the whole score matrix; a q8_0 KV cache halves the memory the growing conversation occupies. Both help some chips and hurt others — which is why they're swept, not defaulted.
Where the kernel exposes the battery's power rails, every configuration is also scored for energy per token. On a phone, a config that's 5% faster but 30% hungrier is a bad trade — efficiency is a ranking axis, not an afterthought.
Measured numbers come from the four phones that have actually been through the harness — MediaTek, Google and Qualcomm silicon: one with i8mm, two with dotprod only, one with neither — and trace to raw JSON in results/. They disagree, and the disagreement is the finding: the same compiler flag buys 1.00×, 3.88×, 4.94× and 5.27×, and the biggest winner is a chip with no i8mm while the pre-dotprod chip gains nothing at all. You can't read the answer off a spec sheet. The kind of each optimization carries over to any Arm phone; its value doesn't, and closing that gap is what the app is for.
Plug in any Android phone. The harness reads its silicon, sweeps the builds, and writes its own JSON — no phone is special-cased.
Everything on this page ships as one Android app. It reads the chip it was installed on, benchmarks the configurations that chip can actually run, applies the winner, and leaves you with a private assistant running exactly that setup.
The harness proves the gains on a bench; the app is where they land. The whole loop of detect, sweep, recommend and apply happens on the phone, with no cloud and no spec-sheet guessing.
Four tabs, one loop. Device reads the Arm features, the core map and what will actually fit in memory. Models recommends the ones matched to this chip — or takes your own GGUF. Tune sweeps thread counts, flash attention and KV-cache layout on the phone itself, scores each result for speed and tokens per joule, and applies the winner. Chat runs the tuned model offline, printing measured tokens per second under every reply. React Native and TypeScript over llama.cpp via llama.rn; the screens above are a Nothing Phone (2a). See the loop step by step ›
Every component — quantization, i8mm, compiler flags, the harness — explained from zero.