DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
FREEDOM251

Freedom251 › Blog › Android

Phone LLM Too Slow? Fix Android’s Native Build Type First

By Freedom251 Team · · 9 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Probably—but not because every phone LLM is inherently 37 times slower. In an October 12 DEV Community post, Pingredsai measured a llama.cpp Android Debug build against a Release build on one Pixel 4. The Release build generated 18.5 tokens per second versus 0.5 tok/s in Debug, a reported 37x difference. The practical lesson is to inspect the native build that CMake actually generated: confirm the build type, optimization flags, and compiled library instead of trusting the Gradle variant name.

The same test reported much larger differences for prompt processing and first-token latency. Those figures are useful diagnostics, not a universal phone-performance law. Your result depends on the device, model and quantization, Android toolchain, native flags, measurement phase, and whether the app is really loading the library you rebuilt.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What did the reported 37x slowdown actually measure?

The comparison was made on a Google Pixel 4 with a Snapdragon 855, running Qwen2.5-1.5B-Instruct in Q4_K_M quantization through an Android llama.cpp build. Pingredsai compared a Debug native build with a Release build and reported these results:

Measured phase Debug Release Reported difference What the phase represents
Token generation 0.5 tok/s 18.5 tok/s 37x Steady-state decoding after the prompt has been processed
First token 1,863 ms 52 ms 36x Time until the first generated token is available
Prefill of 43 tokens 42 seconds 0.556 seconds 75x Processing the input prompt before generation
Model load 24 seconds 3.9 seconds 6x Reading and initializing the model

These are the author’s measurements, not an independent laboratory result or a vendor statistic. Keep the device and Qwen quantization attached to every number: changing either can move the result substantially. Also note that “37x slower” describes the ratio for generation in this test; the reported ratios differ by phase.

#1 Best Overall
Yojaro 4Pack Silicone Suction Phone Case Mount, Silicon Adhesive Smartphones Stand Sticky, Hands-Free Phone Accessories Holder for Selfies and Videos (Black & White & Translucent & Light Pink)
  • 【Strong Adsorption】The inspiration of the silicone phone suction case comes from the adhesive force of the octopus. Each suction cup phone mount is 3.15 inches long and 2.17 inches wide, with 24 independent suction cups providing a stronger and more stable suction force, so you don't have to worry about your phone falling during use.
  • 【Back of Phone Suction Grip】Remove the adhesive film on the phone suction cup and stick it on the phone case. You can then fix the phone on any smooth surface, which is very convenient. (The phone suction cup cannot be removed and reused after being attached to the phone case. It is recommended to attach it to a regular phone case, not a valuable one.)
  • 【Widely Used】Our non-slip silicone phone sticky grip mount attaches to almost any flat phone case and make it compatible with common mobile phones such as iPhone and Android.You can shoot, watch videos or video calls in the kitchen, gym, dance studio, bathroom and other places.
  • 【Capture the Wonderful Picture】Whether you are a TikTok creator or just like to share videos and photos, this phone suction cup can help you hands-free capture wonderful videos and photos for sharing with friends.
  • 【Note】You can fix the phone suction cup on a smooth surface such as a mirror or glass. If necessary, wipe the suction cup with a damp cloth to obtain stronger suction. Before releasing your hand, make sure the phone is firmly fixed. (Not applicable to rough walls, wooden surfaces, and other uneven surfaces)

Why can a Debug native build be so much slower?

Android’s Debug and Release labels can select different CMake configurations for native code. A Debug configuration commonly prioritizes diagnostics, assertions, and debuggability, while an optimized Release configuration allows the compiler to transform hot code aggressively. Pingredsai reported that the generated Debug build did not contain the expected optimization flags.

What optimization changes

Compiler optimization can inline small functions, remove unreachable work, simplify loops, vectorize operations, allocate frequently used values to registers, and eliminate code whose results are never used. In an inference engine, those transformations affect the tight matrix, quantization, and tensor loops that execute for every token. Assertions and other diagnostic checks can add work to those loops as well.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The post presents this as the explanation for its result, not as a controlled experiment isolating one compiler pass. The evidence shows a large Debug-to-Release difference in that configuration; it does not prove that every Android Debug build, every phone, or every llama.cpp revision will show the same ratio.

Why an ARM instruction is not enough

Finding an instruction such as ARM’s sdot in a disassembly proves that some compiled path can use that instruction. It does not prove that the complete program was built with high optimization, that all hot functions use the expected path, or that the library being run is the library you just rebuilt. Instruction-set support and compiler optimization level are separate checks.

How do I check the build that CMake really generated?

Inspect the generated native files, not only the Gradle script. Android projects usually place CMake output under a module’s .cxx directory, with a separate directory for each ABI, variant, and build configuration.

Rank #2
Apple EarPods Headphones with USB-C Plug, Wired Ear Buds with Built-in Remote to Control Music, Phone Calls, and Volume
  • SUPERIOR COMFORT — Unlike traditional circular ear buds, the design of EarPods is defined by the geometry of the ear. Which makes them more comfortable for more people than any other ear bud–style headphones.
  • HIGH-QUALITY AUDIO — The speakers inside EarPods have been engineered to maximize sound output and minimize sound loss, which means you get high-quality audio.
  • BUILT-IN REMOTE — EarPods with USB-C plug also include a built-in remote that lets you adjust the volume, control the playback of music and video, and answer or end calls with a pinch of the cord.
  • COMPATIBILITY — Works with all devices that have a USB-C port.
  • INTEGRATED MICROPHONE — A built-in microphone precisely captures your voice while you’re on the phone, taking a FaceTime call, or summoning Siri — so you’re always heard loud and clear.
  1. Build the exact variant you intend to measure. For a production-style test, invoke the Release variant, for example ./gradlew assembleRelease. If you changed CMake or the toolchain, clean the native output first so an old library cannot survive the reconfiguration.
  2. Locate the generated files. In the relevant .cxx subdirectory, find CMakeCache.txt and build.ninja for the ABI and variant you are running. Do not inspect a different ABI or an earlier build directory.
  3. Read the cache value. Search CMakeCache.txt for CMAKE_BUILD_TYPE, CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, and their Release-specific counterparts. A cache entry that still says Debug explains why a Gradle task named “release” may not have produced the native configuration you expected.
  4. Read actual compile commands. Search build.ninja for a source file from llama.cpp or ggml and inspect the complete command line. Look for the optimization and assertion flags that your toolchain is supposed to pass. A flag in a top-level Gradle file is not evidence that it reached the compile rule.
  5. Confirm the packaged library. Check the APK or app bundle’s native-library contents and load-time logging, where available, to ensure the tested application uses the rebuilt ABI and not a prebuilt copy, a different flavor, or a stale intermediate.

On a Unix-like workstation, searches can be as simple as grep -E 'CMAKE_BUILD_TYPE|CMAKE_C_FLAGS|CMAKE_CXX_FLAGS' CMakeCache.txt and grep -n -- '-O' build.ninja. On Windows, use the equivalent text search in PowerShell or an editor. The important point is to inspect the generated files for the exact ABI and variant.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How can I make the native build use Release optimization?

Set the native configuration before adding llama.cpp, then verify the generated result. The post describes this ordering because a subdirectory can create targets and cache values that are difficult to override later.

# Example pattern; adapt it to your project and toolchain
set(CMAKE_BUILD_TYPE Release CACHE STRING "Native build type" FORCE)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -DNDEBUG" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG" CACHE STRING "" FORCE)

add_subdirectory(llama.cpp)

This is a configuration pattern, not a guarantee for every Android Gradle Plugin, CMake, NDK, or compiler version. Some projects set flags through a toolchain file, target properties, or an external build system; a global cache assignment can then be ignored or can override settings needed elsewhere. Keep the change scoped to the native code you intend to benchmark when possible.

After editing, delete the affected .cxx output or use the project’s clean-and-reconfigure procedure, rebuild the same ABI, and repeat the cache and Ninja-file inspection. If the expected flags do not appear in the compile command, the fix has not reached the compiler yet.

How do I select the correct Android variant?

Gradle’s variant and CMake’s native configuration must agree. In a normal Android project, the release build type should configure external native builds as Release, while debug configures them as Debug. Product flavors can add another dimension, so a task such as assembleDemoRelease may generate a different native directory from assembleRelease.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
PopSockets Adhesive Phone Grip, Holder- Black | Anti-Drop, Kickstand, Secure Comfortable Hold, Black, Create a Mobile Phone Outfit
  • Secure Hold: Our PopSockets adhesive phone grip gives your cell phone a secure, comfortable hold in hand to help prevent drops while texting, taking photos, or scrolling on the go. Designed to stick firmly to most phone cases and devices.
  • Hands-Free Made Easy: Easily turn your PopSocket into a phone stand to prop up your phone anywhere, perfect for watching videos, video calls, or following recipes. A must-have phone holder that keeps your device secure and ready for anything.
  • Compatibility: Works with all phones, tablets, and Kindles. Sticks best to smooth, hard plastic cases and may not adhere to silicone or textured cases. Easily swap your PopTop to change up your style.
  • Black PopSockets: Simple, refined, and endlessly versatile. A timeless essential for any phone.
  • Travel Must-Have for People On the Go: A must-have travel accessory for flights, flying, airports, air travel, airplanes, planes, international trips, cruises, and long travel days. Key gadget for your airport haul, travel accessories and must-haves.
  1. Open the module’s build.gradle or build.gradle.kts and identify the buildTypes, product flavors, and externalNativeBuild block.
  2. Build the exact flavor and build type used by the installed APK.
  3. Find that variant’s native directory under .cxx; do not reuse a cache created for Debug or another flavor.
  4. Install the newly produced APK, then rerun the benchmark without changing the model or prompt.

If Gradle passes a build type explicitly to CMake, that value should appear in CMakeCache.txt. If the cache disagrees with the variant you selected, resolve that mismatch before changing model settings or thread counts.

How should I benchmark the change fairly?

Hold every variable constant except the native build configuration. The reported figures mix four phases, and each phase answers a different user question.

  • Device and thermal state: use the same phone, operating-system state, battery condition, and thermal conditions. A warm handset can throttle during a second run.
  • Model identity: use the same model file, architecture, context length, and quantization. Qwen2.5-1.5B-Instruct Q4_K_M is the specific model used in the reported comparison.
  • Prompt: keep the exact text and token count fixed. The post’s prefill number covers 43 tokens; a longer prompt is a different workload.
  • Measurement phase: record model-load time, prompt prefill, first-token latency, and steady-state generation separately. Combining them into one average can hide which path is slow.
  • Runtime settings: keep thread count, CPU affinity, memory mode, and any hardware-backend setting constant.
  • Toolchain record: write down the Android Gradle Plugin, Gradle, CMake, NDK, compiler, llama.cpp revision, ABI, and effective flags. The available account does not establish the versions used in the original post.
  • Repeated runs: perform a cold-load measurement and additional warm runs, and report whether a value is a median, minimum, or single observation.

Report units as well as ratios. “18.5 tok/s” is meaningful only when readers know the model, device, prompt conditions, and whether it is generation after prefill.

Why might my phone show a much smaller—or larger—difference?

The 37x figure is not a property of phones or language models in general. It is one author’s result for one Snapdragon 855 device, one quantized model, and two native configurations. Newer or older CPUs, different memory systems, different ABIs, and different llama.cpp revisions can change both absolute speed and the size of a Debug penalty.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A build may also contain multiple code paths. One ABI could receive optimized compiler flags while another does not; a prebuilt library could be packaged accidentally; or a runtime dispatch decision could select a fallback kernel. These cases are why checking the generated compile command and the library loaded by the app is more reliable than inferring performance from a Gradle label.

Rank #4
Sale
360° Rotating Stainless Steel Phone Tether Tab (Silvery 3-Pack) - Universal for iPhone & Other Phones (Fits Wristbands/Necklaces/Crossbody Straps)
  • [360 ° Flexible Rotation Design] Comes with a rotatable lanyard ring that supports 360 ° free rotation, effectively solving the problem of twisted and tangled lanyards
  • [Wide compatibility] The ultra-thin 0.02-inch design does not block the charging port at all, and both wired and wireless charging can be used directly without removing the pad. Compatible with most smartphones such as iPhone, compatible with various wristbands, lanyards, crossbody straps, and keychains
  • [Durable and Portable Material] Premium rust-resistant stainless steel material with good flexibility, which not only avoids scratching the phone case, but also has excellent anti rust and anti fading performance
  • [Multi scenario Practical] Paired with a lanyard or wristband, hands-free use can be achieved. The phone is within reach and not easily dropped, ideal for daily commuting and outdoor activities. Suitable for full coverage phone cases, does not support half coverage phone cases
  • [Quality Service] If you find any damage or other issues with the product upon receipt, please contact us immediately. We will handle it quickly
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What should I troubleshoot if Release still runs slowly?

The cache says Debug

Remove the affected native output, verify the variant-to-CMake mapping, and rebuild. A stale cache can preserve an earlier build type even after a Gradle file changes.

The cache says Release but commands lack optimization

Inspect target-specific properties, toolchain files, and generated Ninja rules. Your flags may be assigned before another configuration overwrites them, or they may be attached to a target that llama.cpp does not use.

The flags are present but the app is unchanged

Confirm the APK contains the rebuilt ABI and that the application loads that library. Check for duplicate native libraries, prebuilt artifacts, and flavor-specific output directories.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Only first-token or prefill time is poor

Separate model loading, prompt processing, and generation in your timer. A problem in one phase can be hidden by a healthy steady-state token rate, and the reported Pixel 4 measurements show that the phases can have very different ratios.

Performance falls during a long run

Repeat the test after the phone has cooled and record thermal behavior. Compiler flags cannot prevent frequency reduction caused by heat or power limits.

Best Value
Anteel 2 Pack Silicone Suction Cup Phone Case Mount Double Sided, Hands-Free Silicon Phone Grip with Higher Suction Power for Selfies and Videos, Non Slip Phone Accessories (LightPink&White)
  • 【PKYAA Double Sided Silicone Suction Phone Case Mount】PKYAA With Double Sided 40 Strong and Reliable individual suction cups, PKYAA provides a thicken and upgraded universal silicon suction mount for your phone.
  • 【Friendly to Content Creators】If you are a content creator or an online influencer, you can create videos anywhere with this suction mount completely hands free with this silicone cell phone mount for cases.
  • 【HANDS-FREE & Adhere to Mirrors】This Double Sided silicone suction phone case mount allows you to stick your phone to the mirror easily. No longer holding your phone in one hand to watch video tutorials while making up.
  • 【Strong Grip on the Smooth Surface】You can easily hang your phone anywhere with a smooth surface. All you do is you clean off your phone and smooth surface. It is STURDY and it not only sticks to mirrors, it also sticks to windows, it sticks to refrigerators, tiles and other clean, flat surfaces.
  • 【Press Down Firmly Every 30 Minutes】Use your palm or fingers to press the phone down firmly and check it's secure before letting go. Apply even pressure for a few seconds to allow the suction cup to adhere properly. To maintain the grip and prevent accidental falls, it's a good practice to periodically reapply pressure to the suction cup.

Does seeing sdot prove the fix worked?

No. It demonstrates that a particular instruction is present somewhere in the disassembly, but it does not establish whole-program optimization, complete kernel coverage, or correct library selection. Pair disassembly inspection with the CMake cache, generated compile commands, and an end-to-end benchmark using fixed inputs.

What remains unverified about the 37x claim?

The available account is self-reported. It does not provide an independent reproduction, a complete list of Gradle, Android Gradle Plugin, CMake, NDK, and compiler revisions, or a controlled experiment assigning the speed change to individual optimization passes. That limits how broadly the ratios can be generalized.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a reproducible report, publish the device and processor, Android version, model checksum and quantization, prompt, ABI, all toolchain versions, build type, effective compile flags, thread settings, and separate timings for load, prefill, first token, and generation. Those details let another developer determine whether a mismatch is caused by configuration, workload, or hardware.

What is the fastest practical check?

  1. Run the benchmark once and record which phase is slow.
  2. Identify the exact APK variant and ABI installed on the phone.
  3. Open that variant’s CMakeCache.txt and confirm CMAKE_BUILD_TYPE=Release.
  4. Open its build.ninja and confirm optimization flags on llama.cpp or ggml compile commands.
  5. Clean and rebuild if either check fails.
  6. Rerun with the same Pixel-class device conditions, model file, 43-token prompt where applicable, and runtime settings.

If those checks pass, the original Debug-versus-Release explanation does not account for your remaining slowdown; investigate the selected ABI, runtime backend, thread settings, thermal state, and measurement method instead of assuming another missing compiler switch.

Frequently Asked Questions

Is -O3 always faster than -O2 for mobile inference?

No. Higher optimization can increase code size, alter instruction choices, or expose compiler issues, so it should be measured on the target device. Keep the setting that improves the phase you care about without destabilizing the rest of the application.

Can I distribute an optimized build with assertions enabled?

You can, but assertions add checks and may affect latency in hot native paths. Decide separately whether you need diagnostics in the shipped variant, then benchmark the exact combination of optimization and assertion settings you plan to distribute.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Will changing Debug to Release change the model’s answers?

A normal optimized build is intended to preserve the same computation, but compiler options that permit relaxed floating-point behavior can change numerical results at the margins. Validate output quality when you alter floating-point or fast-math-related options.

How do I compare two phones without misleading tok/s numbers?

Use the same model file, quantization, prompt, context, thread policy, and measurement phase on both devices. Report first-token latency and steady-state generation separately, because one phone can load or prefill faster while generating tokens at a similar rate.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

AndroidCMakecompiler optimizationllama.cppmobile AIperformance

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.