Slow DB Performance - DataStack childTransactionQueue, qos: .utility #421

Open
opened 2025-12-29 18:26:47 +01:00 by adam · 4 comments
Owner

Originally created by @patzootz on GitHub (Oct 22, 2023).

Hi,
I'm building an app that is very db heavy.
I've noticed my inserts using dataStack.perform(asynchronous(()) are slow.
I was able to have double the insert performance by changing DataStack childTransactionQueue QOS to .userInitiated from .utility

(internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue", qos: .userInitiated))

Is there a reason for that queue to have lower priority? Is there a faster way to populate the database?

Originally created by @patzootz on GitHub (Oct 22, 2023). Hi, I'm building an app that is very db heavy. I've noticed my inserts using dataStack.perform(asynchronous(()) are slow. I was able to have double the insert performance by changing DataStack childTransactionQueue QOS to .userInitiated from .utility (internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue", qos: .userInitiated)) Is there a reason for that queue to have lower priority? Is there a faster way to populate the database?
Author
Owner

@JohnEstropia commented on GitHub (Oct 22, 2023):

Asynchronous transactions are executed in a serial queue, so what you're seeing is expected behavior. This ensures that operations within each transaction block do not cause the transactions to conflict with each other.

If you are very sure that your updates will not affect other transactions, feel free to use the DataStack.beginUnsafe() in your own dispatch queue. Just make sure to call transaction.commit() manually as well to save the transaction.

@JohnEstropia commented on GitHub (Oct 22, 2023): Asynchronous transactions are executed in a serial queue, so what you're seeing is expected behavior. This ensures that operations within each transaction block do not cause the transactions to conflict with each other. If you are very sure that your updates will not affect other transactions, feel free to use the `DataStack.beginUnsafe()` in your own dispatch queue. Just make sure to call `transaction.commit()` manually as well to save the transaction.
Author
Owner

@patzootz commented on GitHub (Oct 22, 2023):

Thank you for the fast reply.
Can be any negative effect from increasing the childTransactionQueue priority? If it manages all async transaction why would we want it to have .utility priority instead of .userInitiated?

I've tried the DataStack.beginUnsafe() approach but for some reason the insert performance was very fast at first but got slower as more as i've added objects to the database.

Any idea why?

@patzootz commented on GitHub (Oct 22, 2023): Thank you for the fast reply. Can be any negative effect from increasing the childTransactionQueue priority? If it manages all async transaction why would we want it to have .utility priority instead of .userInitiated? I've tried the `DataStack.beginUnsafe()` approach but for some reason the insert performance was very fast at first but got slower as more as i've added objects to the database. Any idea why?
Author
Owner

@JohnEstropia commented on GitHub (Oct 22, 2023):

.userInitiated will compete with other tasks that are, well, initiated by the user. CoreStore's asynchronous transactions were designed to work with any common tasks, including background tasks not necessarily invoked by the user (ex: regular background server fetches)

Is it possible that your app has too many queues have high priority? That will tend to starve lower priority queues.

Note that .utility is really not that a low priority. Apple recommends it for importing data.

@JohnEstropia commented on GitHub (Oct 22, 2023): `.userInitiated` will compete with other tasks that are, well, initiated by the user. CoreStore's asynchronous transactions were designed to work with any common tasks, including background tasks not necessarily invoked by the user (ex: regular background server fetches) Is it possible that your app has too many queues have high priority? That will tend to starve lower priority queues. Note that `.utility` is really not that a low priority. Apple recommends it for [importing data](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html).
Author
Owner

@patzootz commented on GitHub (Oct 22, 2023):

Looks like i figured it out.
I was doing beginUnsafe each time I've received data from the server (page of 100).
If i share the same unsafeTransaction the performance consists

@patzootz commented on GitHub (Oct 22, 2023): Looks like i figured it out. I was doing beginUnsafe each time I've received data from the server (page of 100). If i share the same unsafeTransaction the performance consists
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore-JohnEstropia#421