mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Various performance tweaks (#474)
* Store and reuse room list placeholder avatars and last messages * Cache and reuse HomeScreenRooms * Reduce RoomSummaryProvider diff collection time * Promote more logs to info * Slighty tweak RustTracing to make it easier to configure * Move TimelineProvider and RoomTimelineController item processing to background queues * Prevent the timeline from stopping an ogoing decelerating scroll when starting backpaginating
This commit is contained in:
@@ -29,6 +29,7 @@ private class RoomTimelineListener: TimelineListener {
|
||||
class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private let serialDispatchQueue: DispatchQueue
|
||||
|
||||
let itemsPublisher = CurrentValueSubject<[TimelineItemProxy], Never>([])
|
||||
|
||||
@@ -40,6 +41,7 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
|
||||
init(roomProxy: RoomProxyProtocol) {
|
||||
self.roomProxy = roomProxy
|
||||
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider")
|
||||
itemProxies = []
|
||||
|
||||
Task {
|
||||
@@ -47,8 +49,8 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
|
||||
roomTimelineListener
|
||||
.itemsUpdatePublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] in self?.updateItemsWithDiff($0) }
|
||||
.collect(.byTime(serialDispatchQueue, 0.025))
|
||||
.sink { [weak self] in self?.updateItemsWithDiffs($0) }
|
||||
.store(in: &cancellables)
|
||||
|
||||
switch await roomProxy.addTimelineListener(listener: roomTimelineListener) {
|
||||
@@ -63,22 +65,25 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateItemsWithDiff(_ diff: TimelineDiff) {
|
||||
private func updateItemsWithDiffs(_ diffs: [TimelineDiff]) {
|
||||
MXLog.verbose("Received timeline diff")
|
||||
|
||||
guard let collectionDiff = buildDiff(from: diff, on: itemProxies) else {
|
||||
MXLog.error("Failed building CollectionDifference from \(diff)")
|
||||
return
|
||||
}
|
||||
|
||||
guard let updatedItems = itemProxies.applying(collectionDiff) else {
|
||||
MXLog.error("Failed applying diff: \(collectionDiff)")
|
||||
return
|
||||
}
|
||||
|
||||
MXLog.verbose("Applied diff \(collectionDiff), new count: \(updatedItems.count)")
|
||||
|
||||
itemProxies = updatedItems
|
||||
itemProxies = diffs
|
||||
.reduce(itemProxies) { currentItems, diff in
|
||||
guard let collectionDiff = buildDiff(from: diff, on: currentItems) else {
|
||||
MXLog.error("Failed building CollectionDifference from \(diff)")
|
||||
return currentItems
|
||||
}
|
||||
|
||||
guard let updatedItems = currentItems.applying(collectionDiff) else {
|
||||
MXLog.error("Failed applying diff: \(collectionDiff)")
|
||||
return currentItems
|
||||
}
|
||||
|
||||
MXLog.verbose("Applied diff \(collectionDiff), new count: \(updatedItems.count)")
|
||||
|
||||
return updatedItems
|
||||
}
|
||||
|
||||
MXLog.verbose("Finished applying diff")
|
||||
}
|
||||
|
||||
@@ -21,10 +21,11 @@ import UniformTypeIdentifiers
|
||||
|
||||
class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
private let userId: String
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let timelineProvider: RoomTimelineProviderProtocol
|
||||
private let timelineItemFactory: RoomTimelineItemFactoryProtocol
|
||||
private let mediaProvider: MediaProviderProtocol
|
||||
let roomProxy: RoomProxyProtocol
|
||||
private let serialDispatchQueue: DispatchQueue
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var timelineItemsUpdateTask: Task<Void, Never>? {
|
||||
@@ -51,10 +52,11 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
self.timelineItemFactory = timelineItemFactory
|
||||
self.mediaProvider = mediaProvider
|
||||
self.roomProxy = roomProxy
|
||||
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider")
|
||||
|
||||
self.timelineProvider
|
||||
.itemsPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.receive(on: serialDispatchQueue)
|
||||
.sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
@@ -236,14 +238,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
updateTimelineItems()
|
||||
}
|
||||
|
||||
private func updateTimelineItems() {
|
||||
timelineItemsUpdateTask = Task {
|
||||
await asyncUpdateTimelineItems()
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
private func asyncUpdateTimelineItems() async {
|
||||
private func updateTimelineItems() {
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
var canBackPaginate = true
|
||||
var isBackPaginating = false
|
||||
|
||||
Reference in New Issue
Block a user