Don't use shared background context for fetching item counts

A significant fraction of the time was spent waiting for the background
context to be available, before the count could even be started. Since
the counts don't need to use the shared background context, let them
each use their own context to avoid contention.
This commit is contained in:
Shadowfacts 2022-09-10 14:14:31 -04:00
parent c78ed42a5e
commit e264e8842c
2 changed files with 11 additions and 9 deletions

View File

@ -77,7 +77,7 @@
</CommandLineArgument> </CommandLineArgument>
<CommandLineArgument <CommandLineArgument
argument = "-com.apple.CoreData.SQLDebug 1" argument = "-com.apple.CoreData.SQLDebug 1"
isEnabled = "YES"> isEnabled = "NO">
</CommandLineArgument> </CommandLineArgument>
</CommandLineArguments> </CommandLineArguments>
<EnvironmentVariables> <EnvironmentVariables>

View File

@ -14,7 +14,7 @@ private let signposter = OSSignposter(subsystem: "net.shadowfacts.Reader", categ
class HomeCollectionViewCell: UICollectionViewListCell { class HomeCollectionViewCell: UICollectionViewListCell {
private var currentItemListType: ItemListType? private var currentItemCountTask: Task<Void, Never>?
private var itemCount: Int? private var itemCount: Int?
#if !targetEnvironment(macCatalyst) #if !targetEnvironment(macCatalyst)
@ -31,12 +31,11 @@ class HomeCollectionViewCell: UICollectionViewListCell {
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
currentItemCountTask?.cancel()
itemCount = nil itemCount = nil
} }
func updateUI(item: ItemListType, persistentContainer: PersistentContainer) { func updateUI(item: ItemListType, persistentContainer: PersistentContainer) {
self.currentItemListType = item
var config = UIListContentConfiguration.valueCell() var config = UIListContentConfiguration.valueCell()
config.text = item.title config.text = item.title
if let itemCount { if let itemCount {
@ -45,10 +44,10 @@ class HomeCollectionViewCell: UICollectionViewListCell {
config.secondaryTextProperties.color = .tintColor config.secondaryTextProperties.color = .tintColor
self.contentConfiguration = config self.contentConfiguration = config
Task(priority: .userInitiated) { currentItemCountTask = Task(priority: .userInitiated) {
let state = signposter.beginInterval("fetch count", id: signposter.makeSignpostID()) let state = signposter.beginInterval("fetch count", id: signposter.makeSignpostID(), "\(String(item.hashValue, radix: 16), privacy: .public)")
if let count = await fetchCount(item: item, in: persistentContainer), if let count = await fetchCount(item: item, in: persistentContainer),
self.currentItemListType == item { !Task.isCancelled {
self.itemCount = count self.itemCount = count
config.secondaryText = count.formatted(.number) config.secondaryText = count.formatted(.number)
self.contentConfiguration = config self.contentConfiguration = config
@ -62,9 +61,12 @@ class HomeCollectionViewCell: UICollectionViewListCell {
return nil return nil
} }
return await withCheckedContinuation({ continuation in return await withCheckedContinuation({ continuation in
let context = persistentContainer.backgroundContext let state = signposter.beginInterval("waiting to perform", id: signposter.makeSignpostID(), "\(String(item.hashValue, radix: 16), privacy: .public)")
context.perform { persistentContainer.performBackgroundTask { context in
signposter.endInterval("waiting to perform", state)
let state = signposter.beginInterval("count", id: signposter.makeSignpostID(), "\(String(item.hashValue, radix: 16), privacy: .public)")
let count = try? context.count(for: request) let count = try? context.count(for: request)
signposter.endInterval("count", state)
continuation.resume(returning: count) continuation.resume(returning: count)
} }
}) })