From 39f49f7033ae998cdd4afd1f05d2679bce0b2ab0 Mon Sep 17 00:00:00 2001 From: Julian Harnath Date: Tue, 26 Dec 2017 17:22:11 +0000 Subject: [PATCH] HaikuDepot: speed up package change handling * During package population, when the repository is being refreshed, thousands of package change messages arrive in MainWindow while the PackageInfo fields are filled with data. Every such message caused a full generation of a package list (including applying filters to all known packages), which is quite slow, and caused the freezing from bug #13823. The list was only used temporarily to figure out if the package should be visible now or not. * Instead of generating a new package list, we now only match the single updated PackageInfo against the current filters. * Fixes #13823 * To reduce CPU usage even more, it would be better to not generate at all, or not subscribe to, package changes while the list is being initially populated, and/or to coalesce all the changes to each package info into one update message (instead of one for title, one for prominence, etc). Deferring subscription requires some additional thought on when to subscribe then, and how to avoid leaving a "hole" where changes would go unnoticed. --- src/apps/haikudepot/model/Model.cpp | 22 ++++++++++++++-------- src/apps/haikudepot/model/Model.h | 3 +++ src/apps/haikudepot/ui/MainWindow.cpp | 3 +-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/apps/haikudepot/model/Model.cpp b/src/apps/haikudepot/model/Model.cpp index 4093cea9b0..3188b24189 100644 --- a/src/apps/haikudepot/model/Model.cpp +++ b/src/apps/haikudepot/model/Model.cpp @@ -439,15 +439,8 @@ Model::CreatePackageList() const for (int32 j = 0; j < packages.CountItems(); j++) { const PackageInfoRef& package = packages.ItemAtFast(j); - if (fCategoryFilter->AcceptsPackage(package) - && fSearchTermsFilter->AcceptsPackage(package) - && fIsFeaturedFilter->AcceptsPackage(package) - && (fShowAvailablePackages || package->State() != NONE) - && (fShowInstalledPackages || package->State() != ACTIVATED) - && (fShowSourcePackages || !is_source_package(package)) - && (fShowDevelopPackages || !is_develop_package(package))) { + if (MatchesFilter(package)) resultList.Add(package); - } } } @@ -455,6 +448,19 @@ Model::CreatePackageList() const } +bool +Model::MatchesFilter(const PackageInfoRef& package) const +{ + return fCategoryFilter->AcceptsPackage(package) + && fSearchTermsFilter->AcceptsPackage(package) + && fIsFeaturedFilter->AcceptsPackage(package) + && (fShowAvailablePackages || package->State() != NONE) + && (fShowInstalledPackages || package->State() != ACTIVATED) + && (fShowSourcePackages || !is_source_package(package)) + && (fShowDevelopPackages || !is_develop_package(package)); +} + + bool Model::AddDepot(const DepotInfo& depot) { diff --git a/src/apps/haikudepot/model/Model.h b/src/apps/haikudepot/model/Model.h index fa852b176a..a4baa39841 100644 --- a/src/apps/haikudepot/model/Model.h +++ b/src/apps/haikudepot/model/Model.h @@ -72,6 +72,9 @@ public: // !Returns new PackageInfoList from current parameters PackageList CreatePackageList() const; + bool MatchesFilter( + const PackageInfoRef& package) const; + bool AddDepot(const DepotInfo& depot); bool HasDepot(const BString& name) const; const DepotList& Depots() const diff --git a/src/apps/haikudepot/ui/MainWindow.cpp b/src/apps/haikudepot/ui/MainWindow.cpp index 3a8fdd1193..bc8d021bdf 100644 --- a/src/apps/haikudepot/ui/MainWindow.cpp +++ b/src/apps/haikudepot/ui/MainWindow.cpp @@ -487,8 +487,7 @@ MainWindow::MessageReceived(BMessage* message) BAutolock locker(fModel.Lock()); // The package didn't get a chance yet to be in the // visible package list - PackageList visiblePackages = fModel.CreatePackageList(); - isVisible = visiblePackages.Contains(ref); + isVisible = fModel.MatchesFilter(ref); // Transfer this single package, otherwise we miss // other packages if they appear or disappear along