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.
This commit is contained in:
Julian Harnath 2017-12-26 17:22:11 +00:00
parent 95c9effd68
commit 39f49f7033
3 changed files with 18 additions and 10 deletions

View File

@ -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)
{

View File

@ -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

View File

@ -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