Skip to main content

Crate asc_cache

Crate asc_cache 

Source
Expand description

Caches for inflated DEX entries and what is derived from them.

Inflating the largest DEX of an APK is the critical path of every query, and it produces the same bytes every time. Two caches remove that cost for repeated queries without introducing any preprocessing step: they are filled lazily by the first query that needs an entry.

  • DiskCache stores data under a cache directory keyed by the APK’s size, modification time and central directory (ApkKey), in three tiers (Tier) that share one budget:

    • L1 inflated DEX entries (DiskCache::put / DiskCache::get), cheap to rebuild and large: evicted first, largest-and-oldest first. Entries below DiskCache::min_dex_bytes are not worth writing (re-inflating them is cheaper than the write).
    • L2 derived indexes (DiskCache::put_derived / DiskCache::get_derived): locator tables and other per-DEX or per-APK structures, stored so they can be mapped and viewed in place. Every process mapping one shares its pages instead of building a private copy. Kept by rebuild cost per byte; evicted last.
    • L3 rendered results (DiskCache::put_rendered / DiskCache::get_rendered): small outputs keyed by the query and the tool version, plain LRU under a small budget of their own.

    Later processes memory-map L1 and L2 files, so the operating system’s page cache keeps them hot. Writes are plain puts; eviction is a separate DiskCache::evict step so a host can batch it (writing a 30 MiB entry and walking the whole cache directory after every one of them is what a query must never wait on). The budget follows the free space of the file system by default (AutoDisk).

    Writes are never synced: everything here can be rebuilt, and a sync per file costs more than the query that wrote it (macOS flushes the drive’s own cache on every one). A temporary file renamed into place keeps readers from seeing half a file while the system runs; what a crash can leave is a file whose pages never reached the disk. Every file carries a CRC-32 of its contents, checked when a file last written before the current boot (or at an unknown or future time) is first read: a damaged one is deleted and read as a miss. L3 files are small and always checked.

  • MemoryCache is a byte-bounded LRU of inflated entries for hosts that stay alive between queries (MCP servers, the daemon).

  • ProcessRegistry lets resident hosts of one user see each other, so their memory budgets add up to one machine-wide budget, and auto_threads splits the CPUs between the busy ones.

Structs§

ApkKey
Identity of an APK for cache purposes.
AutoDisk
The automatic disk budget: a share of what the cache could occupy (its own bytes plus the free space), at most a ceiling, and never more than leaves auto_disk_reserve free.
Derived
A derived index mapped from L2: the payload DiskCache::put_derived stored, 64-byte aligned.
DiskBudget
What DiskCache::budget reports.
DiskCache
On-disk cache of inflated entries, derived indexes and rendered results.
MemoryCache
Byte-bounded LRU of inflated entries plus any per-entry state the host wants to keep alongside (T).
ProcessRegistry
This process’s entry in a registry directory; removed on drop.
ProcessUsage
Another registered process.
Rendered
A validated L3 result viewed directly in its cache file.
TierStats
Per-tier usage reported by DiskCache::tier_stats.

Enums§

CacheError
Why a disk cache operation failed.
DexData
Inflated bytes of one entry, either owned or mapped from the disk cache.
DiskCapacity
How a DiskCache is bounded.
Threads
Worker threads of a search.
Tier
The tiers of a DiskCache.

Constants§

AUTO_DISK_RESERVE_MIN
Smallest free space the automatic budget leaves on the file system; the reserve is the larger of this and AUTO_DISK_RESERVE_PERCENT of it.
AUTO_DISK_RESERVE_PERCENT
Share of the file system’s size, in percent, the automatic budget leaves free (at least AUTO_DISK_RESERVE_MIN).
AUTO_DISK_UNKNOWN
The automatic disk budget where the free space cannot be read.
CACHEDIR_TAG
Marker file written into the cache root (see https://bford.info/cachedir/). A directory is only used as a cache (written to, evicted, cleared) when it carries this marker, is empty or missing, or holds nothing but the cache’s own APK directories (one written before the marker existed). Pointing --cache-dir at $HOME or a project tree therefore neither reclaims its subdirectories as “least recently used APKs” nor plants a tag that makes backup tools skip it.
DECOMPILERS_DIR
Subdirectory holding the working directories of decompiler backends (decompilers/<name>/); the cache neither evicts nor clears it.
DEFAULT_MIN_DERIVED_COST
Derived indexes that took less than this to build are not written to L2 by default: mapping and checking a file would save next to nothing.
DEFAULT_MIN_DEX_BYTES
Inflated DEX entries smaller than this are not written to L1 by default: re-inflating them costs less than writing (and later evicting) them.
DERIVED_BUDGET_DIVISOR
L2 never takes more than 1/DERIVED_BUDGET_DIVISOR of the total budget.
MAPPED_CHARGE_DIVISOR
A memory budget charges file-backed bytes (mapped from the disk cache, the APK or a HarmonyOS package) at this fraction of their size, heap bytes in full.
RENDERED_BUDGET_DIVISOR
L3 never takes more than 1/RENDERED_BUDGET_DIVISOR of the total budget.
RENDERED_MAX
Absolute cap of L3, which also never takes more than 1/RENDERED_BUDGET_DIVISOR of the total budget.
SPILL_DIR
Where the MCP server writes replies too long for the client (its own budget and pruning; this cache only recognizes and clears it).

Traits§

LockExt
Locking a Mutex whose state can be thrown away after a panic.

Functions§

auto_disk_reserve
Free space the automatic budget never writes into on a file system of total bytes.
auto_threads
Worker threads of a search whose caller fixed none: this machine’s CPUs split between this process and the user’s other busy registered ones (auto_threads_for). Re-read at most every 100 ms, so a sweep follows the others starting and finishing their scans (Threads::wait_turn). A process that does not register itself (a one-shot command) still gives way to the resident hosts.
auto_threads_for
4 x cpus workers split evenly between this process and busy_others, at most cpus and at least 2 (where there are 2): a scan on one thread gives up its overlap of inflating one entry while searching another. Up to 4 busy processes each keep every CPU.
cpus
This machine’s CPUs.
disk_space
(free, total) bytes of the file system holding path (or its nearest existing ancestor). None where it cannot be determined.
rendered_key
The key an L3 result is stored under: the producer (e.g. findrefs) and its version, the L3 layout version and the query, so a tool upgrade never serves output of the old one.