UnigramDev/Unigram/composer-typing-performance • 0827fe2 • 2 files, +59/-0
Add a profiler for scoped timings
Begin and End are [Conditional("INSTRUMENTATION")] like Instrumentation.Register,
so a probe can sit permanently at a call site and compiles out of every build
that doesn't define the symbol. A helper returning a timestamp cannot do that:
the reading itself would stay in the hot path, which is where these get placed.
Scopes nest and are reported indented, so an outer scope shows what it contains.
End unwinds to its own label, so a return between a pair reports the abandoned
scopes rather than silently charging the rest of the run to them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
UnigramDev/Unigram/composer-typing-performance • fc25f0d • 1 files, +122/-109
Probe the document once instead of walking it on every keystroke
UpdateFormat, UpdateCustomEmoji and UpdateBlocks each walked the whole document
on every keystroke. The editor breaks character format runs at every space, so
the first of those was O(words) round trips into the text host per character
typed.
TOM reports a property as undefined when it isn't uniform over a range, so a
single read over the whole story says whether there is anything to walk for at
all: no hidden text means no custom emoji, a uniform SpaceAfter of zero means no
blockquote, and a document already at the regular size has no font size to fix.
Alongside that: the ranges these walk with are kept and moved rather than
allocated on each pass, since every ITextRange is a COM object; applying
entities in SetText reuses one range instead of one per entity; and UpdateBlocks
removed stale blockquote decorations with an index loop that skipped every other
element.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
UnigramDev/Unigram/composer-typing-performance • dc8291a • 1 files, +26/-6
Stop allocating per character in the emoticon replacement
OnCharacterReceived runs for every character typed. It built a byte array and a
string just to recover the first char of the code point, then used Max and a
capturing FirstOrDefault over the candidates. The first char comes straight off
the code point now and the two LINQ calls are loops.
The Consolas check moved behind the candidate lookup, so a keystroke that can't
end an emoticon no longer pays for a call into the text host, and EndsWith is
ordinal.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
UnigramDev/Unigram/composer-typing-performance • eb2e555 • 1 files, +14/-12
Don't recreate every custom emoji source on each keystroke
UpdateEntities assigned a new CustomEmojiFileSource to every player on every
text change. Each one sends getCustomEmojiStickers from its constructor and
re-runs AnimatedImage.Load. It only assigns when the id actually differs now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#unigram
Post #20600
45