FontDecompressor: eliminate persistent hot group buffer
The hot group buffer (formerly up to 50 KB BSS / heap) is removed. During prewarm, each group is now decompressed into a transient malloc that is freed immediately after its glyphs are extracted — only one group buffer and the page buffer coexist at a time. For getBitmap() cache misses (rare: only hit when a glyph wasn't covered by prewarm), the group is also decompressed transiently and freed after the single glyph is compacted into _hotGlyphBuf. Peak heap during prewarm is now: page buffer + one group buffer. Outside of prewarm, heap usage is only the page buffer itself. Works correctly for large future fonts (Vietnamese, CJK) regardless of group size, with no permanent allocation overhead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
80722118a2
commit
e76118dff0
@@ -19,7 +19,7 @@ class FontDecompressor {
|
||||
// Checks the page buffer (from prewarm) first, then falls back to the hot group slot.
|
||||
const uint8_t* getBitmap(const EpdFontData* fontData, const EpdGlyph* glyph, uint32_t glyphIndex);
|
||||
|
||||
// Free all cached data (page buffer + hot group).
|
||||
// Free all cached data (page buffers).
|
||||
void clearCache();
|
||||
|
||||
// Pre-scan UTF-8 text and extract needed glyph bitmaps into a flat page buffer.
|
||||
@@ -34,8 +34,7 @@ class FontDecompressor {
|
||||
uint16_t uniqueGroupsAccessed = 0;
|
||||
uint32_t pageBufferBytes = 0; // pageBuffer allocation
|
||||
uint32_t pageGlyphsBytes = 0; // pageGlyphs lookup table allocation
|
||||
uint32_t hotGroupBytes = 0; // current hot group allocation
|
||||
uint32_t peakTempBytes = 0; // largest temp buffer in prewarm
|
||||
uint32_t peakTempBytes = 0; // largest temp buffer in prewarm or getBitmap miss
|
||||
uint32_t getBitmapTimeUs = 0; // cumulative getBitmap time (micros)
|
||||
uint32_t getBitmapCalls = 0; // number of getBitmap calls
|
||||
};
|
||||
@@ -65,22 +64,11 @@ class FontDecompressor {
|
||||
|
||||
static constexpr uint16_t HOT_GLYPH_BUF_SIZE = 512; // largest packed single glyph
|
||||
|
||||
// Hot group: single heap buffer sized to the largest group of the active font.
|
||||
// Allocated once per font (lazily in ensureHotGroupBuf) and freed in freeHotGroup().
|
||||
// Single malloc per font session — no repeated alloc/free per page.
|
||||
const EpdFontData* hotGroupFont = nullptr;
|
||||
uint16_t hotGroupIndex = UINT16_MAX;
|
||||
uint32_t _hotGroupBufUsed = 0;
|
||||
uint8_t* _hotGroupBuf = nullptr;
|
||||
uint32_t _hotGroupBufSize = 0;
|
||||
|
||||
// Scratch buffer for compacting a single glyph out of the byte-aligned hot group.
|
||||
// Scratch buffer for compacting a single glyph after a getBitmap() miss.
|
||||
// Valid until the next getBitmap() call.
|
||||
uint8_t _hotGlyphBuf[HOT_GLYPH_BUF_SIZE];
|
||||
|
||||
void freePageBuffer();
|
||||
void freeHotGroup();
|
||||
bool ensureHotGroupBuf(const EpdFontData* fontData);
|
||||
uint16_t getGroupIndex(const EpdFontData* fontData, uint32_t glyphIndex);
|
||||
uint32_t getAlignedOffset(const EpdFontData* fontData, uint16_t groupIndex, uint32_t glyphIndex);
|
||||
bool decompressGroup(const EpdFontData* fontData, uint16_t groupIndex, uint8_t* outBuf, uint32_t outSize);
|
||||
|
||||
Reference in New Issue
Block a user