[PR #666] [MERGED] fix: stable grapheme across frames #1480

Closed
opened 2026-03-14 09:38:59 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/anomalyco/opentui/pull/666
Author: @simonklee
Created: 2/10/2026
Status: Merged
Merged: 2/12/2026
Merged by: @kommander

Base: mainHead: graphene-cache


📝 Commits (1)

  • f05f1cd grapheme: intern pool IDs to stabilize diff across frames

📊 Changes

4 files changed (+207 additions, -14 deletions)

View changed files

📝 packages/core/src/zig/grapheme.zig (+107 -1)
📝 packages/core/src/zig/renderer.zig (+3 -13)
📝 packages/core/src/zig/tests/grapheme_test.zig (+50 -0)
📝 packages/core/src/zig/tests/renderer_test.zig (+47 -0)

📄 Description

The renderer diff compares Cell.char values to decide what changed between frames. For grapheme cells, the char value embeds a pool ID. Without interning, drawing the same "👋" on two consecutive frames produces two different IDs, so the diff treats every grapheme cell as dirty every frame.

This adds content-addressed interning to GraphemePool: when bytes are already live in the pool, alloc() returns the existing ID instead of allocating a new slot. The intern map is maintained on refcount transitions (interned at 0->1, removed at 1->0), so it stays in sync with the pool's own lifetime tracking.

Maybe most important change is to switch from setRaw() to set(). set() is a bit more expensive, but transfers ownership through the tracker. Its also just called for changed cells, so the perf impact should be acceptable.

Fix #667


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/anomalyco/opentui/pull/666 **Author:** [@simonklee](https://github.com/simonklee) **Created:** 2/10/2026 **Status:** ✅ Merged **Merged:** 2/12/2026 **Merged by:** [@kommander](https://github.com/kommander) **Base:** `main` ← **Head:** `graphene-cache` --- ### 📝 Commits (1) - [`f05f1cd`](https://github.com/anomalyco/opentui/commit/f05f1cda8ed2e998e0e97500f0fc5ef1d3dc8f10) grapheme: intern pool IDs to stabilize diff across frames ### 📊 Changes **4 files changed** (+207 additions, -14 deletions) <details> <summary>View changed files</summary> 📝 `packages/core/src/zig/grapheme.zig` (+107 -1) 📝 `packages/core/src/zig/renderer.zig` (+3 -13) 📝 `packages/core/src/zig/tests/grapheme_test.zig` (+50 -0) 📝 `packages/core/src/zig/tests/renderer_test.zig` (+47 -0) </details> ### 📄 Description The renderer diff compares `Cell.char` values to decide what changed between frames. For grapheme cells, the char value embeds a pool ID. Without interning, drawing the same "👋" on two consecutive frames produces two different IDs, so the diff treats every grapheme cell as dirty every frame. This adds content-addressed interning to GraphemePool: when bytes are already live in the pool, alloc() returns the existing ID instead of allocating a new slot. The intern map is maintained on refcount transitions (interned at 0->1, removed at 1->0), so it stays in sync with the pool's own lifetime tracking. Maybe most important change is to switch from setRaw() to set(). set() is a bit more expensive, but transfers ownership through the tracker. Its also just called for changed cells, so the perf impact should be acceptable. Fix #667 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-14 09:38:59 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/opentui#1480
No description provided.