Move profile update handling from notes to the background
During profiling, I found that some large hangs were being caused by a large number of `notify` calls (and their handling functions) keeping the main thread overly busy. We cannot move the `notify` mechanism to a background thread (It has to be done on the main actor or else runtime warnings/errors appear), so instead this commit removes a very large source of notify calls/handling around NoteContentView, and replaces it with a background task that streams for profile updates and only updates its view when a relevant profile is updated. Changelog-Changed: Improved performance around note content views to prevent hangs Closes: https://github.com/damus-io/damus/issues/3439 Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
@@ -101,10 +101,17 @@ extension NostrNetworkManager {
|
||||
relevantStream.continuation.yield(profile)
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the rest of the app so views that rely on rendered text (like mention strings)
|
||||
// can reload and pick up the freshly fetched profile metadata.
|
||||
notify(.profile_updated(.remote(pubkey: metadataEvent.pubkey)))
|
||||
}
|
||||
|
||||
/// Manually trigger profile updates for a given pubkey
|
||||
/// This is useful for local profile changes (e.g., nip05 validation, donation percentage updates)
|
||||
func notifyProfileUpdate(pubkey: Pubkey) {
|
||||
if let relevantStreams = streams[pubkey] {
|
||||
guard let profile = ndb.lookup_profile_and_copy(pubkey) else { return }
|
||||
for relevantStream in relevantStreams.values {
|
||||
relevantStream.continuation.yield(profile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +128,29 @@ extension NostrNetworkManager {
|
||||
}
|
||||
}
|
||||
|
||||
func streamProfiles(pubkeys: Set<Pubkey>) -> AsyncStream<ProfileStreamItem> {
|
||||
guard !pubkeys.isEmpty else {
|
||||
return AsyncStream<ProfileStreamItem> { continuation in
|
||||
continuation.finish()
|
||||
}
|
||||
}
|
||||
|
||||
return AsyncStream<ProfileStreamItem> { continuation in
|
||||
let stream = ProfileStreamInfo(continuation: continuation)
|
||||
for pubkey in pubkeys {
|
||||
self.add(pubkey: pubkey, stream: stream)
|
||||
}
|
||||
|
||||
continuation.onTermination = { @Sendable _ in
|
||||
Task {
|
||||
for pubkey in pubkeys {
|
||||
await self.removeStream(pubkey: pubkey, id: stream.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Stream management
|
||||
|
||||
|
||||
Reference in New Issue
Block a user