UnigramDev/Unigram/develop • e11f632 • 3 files, +244/-90
Fan out the batched TDLib requests, and triage the rest of P2
Applying the rate check that reversed the ConcurrentDictionary item to the rest
of the performance section. Three of the eight items survive it, two are fixed
elsewhere in kind, and two are closed as not worth doing.
The one that gets stronger under scrutiny is the batched requests, because it is
latency rather than throughput and it sits on a path a person waits on.
GetMessageProperties was issued one message at a time, so selecting a hundred
messages meant a hundred sequential round trips before the toolbar could decide
which actions to offer. That and the three others — reactions, custom emoji
sticker sets, message effects — now issue their requests together and await them
as a group.
Two things worth knowing about that change. GetMessageEffectsAsync keeps its
results in request order by indexing them by position: the effect drawer and the
reaction menu both display them in the order they asked for, and the obvious
rewrite of appending fetched results after cached ones silently reorders them.
And the caches are still written in one loop after the group completes, on one
thread, so this does not worsen the open finding about _cachedReactions being an
unsynchronised Dictionary. GetAllReactionsAsync was a verbatim copy of
GetReactionsAsync and now calls it.
OwnedStarCount and OwnedGramCount sent a request on every read until the update
landed, and they are read from bindings, which re-evaluate. Guarded now, and
reset in Clear() so a new authorization fetches again.
GetChatFolders allocated a closure over this on every chat cell that showed a
folder tag. That is now a field built once. The O(n log n) framing in the review
was overstated: a chat is usually in one or two folders, so the sort ran about
one comparison, and a chat in none allocates nothing at all. Rewriting it to
walk the folder list instead would have been slower, since it turns the common
empty case from scanning two entries into scanning every folder.
ReaderWriterDictionary.Find wrapped its predicate in a lambda for
FirstOrDefault, allocating a closure and an enumerator per call.
Closed without changes, both recorded in the review with the arithmetic: the
105-case type switch in OnResult costs 100-200ns against an update rate of tens
per second normally and thousands during a sync, so a dispatch table buys
nothing; and the service construction inside GetChats cannot move to
UpdateSupergroup, because that update carries a supergroup id and there is no
supergroup-to-chat index to get back to the Chat, making GetChats the only place
that notices a supergroup which became a forum after its updateNewChat.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
UnigramDev/Unigram/develop • 9b56b0c • 1 files, +44/-23
Record the review decisions, and what m_impl is actually racing
Five open questions were accepted as they stand and one deferred upstream, so
the list of genuinely open items is down to three.
The m_impl item was filed as theoretical and is not. VoipManager is safe, since
every managed call site including Dispose runs under _managerLock. VoipGroupCall
has no such lock and reaches Dispose from TDLib update thread while the UI thread
calls in, so Stop resetting m_impl there is a use-after-free.
Also corrects the reason I gave for leaving it alone: guarding m_impl would not
put a lock back on the path into managed code, because the callbacks never touch
m_impl.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#unigram
UnigramDev/Unigram/develop • e11f632 • 3 files, +244/-90 Fan out the batched TDLib requests, and tri
Telegram github commits and releases
@tgappsupdatesBroadcast from the most important Telegram clients' repositories
4,538 مشتركًا
فتح في تيليجرام