You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf(editor): cache root TextSpan in QueryaHighlightController to eliminate allocations on cursor blinks #1544
In QueryaHighlightController.buildTextSpan (lib/core/editor/querya_highlight_controller.dart), buildTextSpan is invoked twice per second for cursor blink repaints.
Even on a full cache hit (_cachedText == text), it unconditionally allocates a new wrapper TextSpan and a new List<TextSpan> (TextSpan(style: style, children: [_cachedSpan!])).
Over a session, background cursor blinks across multiple open editor tabs churn unnecessary garbage collection cycles.
Solution
Cache the outer root TextSpan directly (_cachedRootSpan), invalidating it only when the text content, base style, or theme brightness changes.
Return the cached root span directly on cache hits without allocating a new wrapper TextSpan or children list.
Benefits
0 allocations per cursor blink cycle on idle editors.
Reduced GC pressure when multiple SQL editor tabs are active.
Closing as not worth doing. Checked against the code and the Flutter sources:
The premise is off: the cursor blink does not call buildTextSpan. EditableText blinks by changing the cursor opacity on the RenderEditable; it does not rebuild. buildTextSpan runs on rebuilds such as text, selection and focus changes.
On those rebuilds the new root TextSpan costs one object and a one-element list. RenderEditable.text compares it with ==. TextSpan == compares the children with listEquals, and the only child is the cached _cachedSpan itself, so the comparison ends at identical in O(1) and no relayout follows.
Caching the root would save those two small allocations per rebuild and nothing measurable. #1522 is the same proposal and is closed with this.
Activity
ZhuchkaTriplesix commentedon Oct 17, 2026
Closing as not worth doing. Checked against the code and the Flutter sources:
buildTextSpan. EditableText blinks by changing the cursor opacity on the RenderEditable; it does not rebuild.buildTextSpanruns on rebuilds such as text, selection and focus changes.TextSpancosts one object and a one-element list.RenderEditable.textcompares it with==.TextSpan ==compares the children withlistEquals, and the only child is the cached_cachedSpanitself, so the comparison ends atidenticalin O(1) and no relayout follows.Caching the root would save those two small allocations per rebuild and nothing measurable. #1522 is the same proposal and is closed with this.