From 25ff76e1e52b6c5a314c28b2ba97ad3bd000c106 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 10 Sep 2018 22:08:38 -0700 Subject: [PATCH] Fix a performance bug when fetching all unread articles. When validating unread counts, it was looping through the entire set of articles once per feed. Now it loops through articles just once, for a major performance boost with lots of feeds and/or lots of unread articles. --- Frameworks/Account/Account.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 56bcfe44c..b9a8b60f2 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -338,7 +338,22 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, let feeds = container.flattenedFeeds() let articles = database.fetchUnreadArticles(for: feeds.feedIDs()) - feeds.forEach { validateUnreadCount($0, articles) } + + // Validate unread counts. This was the site of a performance slowdown: + // it was calling going through the entire list of articles once per feed: + // feeds.forEach { validateUnreadCount($0, articles) } + // Now we loop through articles exactly once. This makes a huge difference. + + var unreadCountStorage = [String: Int]() // [FeedID: Int] + articles.forEach { (article) in + precondition(!article.status.read) + unreadCountStorage[article.feedID, default: 0] += 1 + } + feeds.forEach { (feed) in + let unreadCount = unreadCountStorage[feed.feedID, default: 0] + feed.unreadCount = unreadCount + } + return articles }