Skip to content

Commit 25bfecf

Browse files
committed
perf(measurement): line-metrics cache stops adding when full, not clear-on-overflow
The process-wide line-metrics cache clear()-ed every entry once it passed 50,000 distinct styles — a non-atomic check-then-clear that is a thundering-herd recompute under concurrent rendering. Stop inserting at the cap and keep the existing entries instead; this runs only on a cache miss, never on the per-measurement get() path. Measured line metrics are unchanged. Distinct styles are few in real use, so this only guards a pathological style explosion. Finding 13 (cache). (The width-cache LRU, Finding 9, was dropped: it added a per-get reorder cost to the hot path for a rare-overflow benefit.)
1 parent 031db67 commit 25bfecf

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ Open cycle — bug-fix / housekeeping. Entries land here as they merge.
8080
large table this removes the dominant per-cell layout allocation. No public API
8181
or behaviour change.
8282

83+
- **Process-wide line-metrics cache stops inserting instead of flushing when full.**
84+
The static line-metrics cache `clear()`-ed every entry once it passed 50,000
85+
distinct styles — a full flush whose non-atomic check-then-clear is a
86+
thundering-herd recompute under concurrent rendering. It now stops inserting at
87+
the cap and keeps the existing entries (distinct styles are few in real use, so
88+
this is only a pathological-explosion guard; it runs on a cache miss, never on
89+
the per-measurement path). **Measured line metrics are unchanged.** No public API
90+
or behaviour change.
91+
8392
### Tests / tooling
8493

8594
- **Benchmark regression gate and measurement probe (benchmarks module, not part

src/main/java/com/demcha/compose/engine/measurement/FontLibraryTextMeasurementSystem.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,16 @@ private GlobalPdfStyleKey globalPdfStyleKey(PdfFont font, TextStyle style) {
100100
}
101101

102102
private static void cacheGlobalLineMetrics(GlobalPdfStyleKey key, LineMetrics metrics) {
103-
if (GLOBAL_PDF_LINE_METRICS_CACHE.size() > GLOBAL_LINE_METRICS_CACHE_LIMIT) {
104-
GLOBAL_PDF_LINE_METRICS_CACHE.clear();
103+
// Safety cap on the process-wide line-metrics cache. Distinct styles are
104+
// few in real use (a handful of font/size/decoration combos); this only
105+
// guards a pathological style explosion. Stop inserting once full instead
106+
// of clear()-ing: the old full flush wiped every hot entry under
107+
// concurrent rendering (a thundering-herd recompute), so keeping the
108+
// existing entries is strictly better. This runs on a cache miss only,
109+
// never on the per-measurement get() path.
110+
if (GLOBAL_PDF_LINE_METRICS_CACHE.size() < GLOBAL_LINE_METRICS_CACHE_LIMIT) {
111+
GLOBAL_PDF_LINE_METRICS_CACHE.putIfAbsent(key, metrics);
105112
}
106-
GLOBAL_PDF_LINE_METRICS_CACHE.putIfAbsent(key, metrics);
107113
}
108114

109115
@Override

0 commit comments

Comments
 (0)