-
-
Notifications
You must be signed in to change notification settings - Fork 1
Performance
delamain is built for headless, concurrent, low-memory operation. This page summarizes real measurements on a large Android app and contrasts the headless architecture with a conventional GUI-mode baseline — a JADX‑GUI‑backed MCP server that drives decompilation through the desktop engine — on identical workloads.
How this was measured. One large production APK (~238,000 classes), a single 62 GB host, client on
--network host(localhost — no LAN jitter, absolute numbers comparable). delamain ran with-Xmx38g -XX:+UseG1GC. P50 over 200 samples × 3 repeats after warmup discards; 503s / timeouts counted separately from latency. These are indicative of the architecture on a large app, not a universal guarantee — your APK, host, and heap will differ.
The headless design keeps a per-class decompile lock plus a persistent CodeStore and usage graph, so it never serializes on a single global decompile lock the way a GUI-driven engine does. Under concurrency this is the sharpest difference:
| Workload (concurrency) | delamain | GUI-mode baseline |
|---|---|---|
| smali @ c8 / c24 | 100% success (0% 503) | 44% / 28% 503 |
| xref, class-level @ c1–c24 | 100% success (0% 503) | 100% 503 (every concurrency level) |
delamain returns 0% 503 across every workload and concurrency level, while the GUI-mode baseline sheds smali requests under load and cannot serve class-level xref at all under concurrency (its global decompile lock serializes everything). An earlier baseline run also saw ~10% 503 on class_source at 10-way concurrency, from JVM heap-pressure tripping its OOM breaker.
REST layer, concurrency 1 / 8 / 24:
| Workload | delamain c1 | c8 | c24 |
|---|---|---|---|
| metadata search | 26 | 298 | 628 |
| class_source (cached) | 5 | 26 | 120 |
| smali | 5.6 | 36 | 135 |
| xref (class-level) | 2.7 | 23 | 102 |
A later tuned build measured cached class_source at 4.7 ms P50 (c1) / 23.4 ms (c8) and class-level xref at 2.4 ms / 22.9 ms, at 0% error.
Noise floor (/health P50): delamain 2.6 ms vs the GUI-mode baseline 21 ms — roughly 8× lower base overhead.
The Python MCP gateway adds ~12–15 ms/call over the raw REST layer (MCP protocol + serialization + one extra hop): metadata +13 ms, class_source +15 ms, smali +14 ms at c1. The full MCP chain stays 100% success.
| Metric | Cold (empty index volume) | Hot (FAST_RESTORE, reused index) |
|---|---|---|
| Serveable (port open, class tree loaded) | ~24 s | ~11–58 s (OS page-cache variance) |
| Full warmup | 1033 s (~17 min) | ~40 s (≈26× faster) |
First-touch uncached class_source
|
~15 s | ms-level after restore |
| On-disk index size | 3.7 GB | reused |
Cold warmup is dominated by Phase-1 full decompile (58%) + use-places harvest (33%). A persisted index volume (see Deployment → prebaked index) collapses restart to ~40 s. Capabilities open progressively during warmup — get_warmup_status reports overall progress, an ETA, and a per-capability ready | warming map (metadata_search → class_source → smali → code_search → xref_class_level → precise_xref_snippets).
On the same ~238K-class app, delamain held ~10 GB steady-state heap (24% of a 38 GB max) with 0 OOM. Under pressure it uses heap-aware degradation — skipping the trigram / use-places index rather than crashing — so it stays alive on constrained hosts. See Configuration for the memory knobs (JADX_CACHE_MAX_GB, warmup worker counts, trigram caps).
- Measured on one large APK, on one host (localhost), with a single cold run — treat as indicative, not a guarantee.
- The GUI-mode comparison is at the REST layer; the baseline's MCP endpoint used a separate auth and was not measured end-to-end.
- Latency and warmup time scale with your APK size, host CPU/RAM, and JVM heap.
See also: Deployment · Configuration · FAQ · Development-and-Integration