To improve responsiveness, some synchronous methods that used FMDB to execute SQLite queries on the main thread were rewritten to be asynchronous, and run in the background via -performSelectorInBackground:withObject:. SQLite not being thread-safe, however, each of these methods would ultimately call -[FMDatabase open], decreasing overall performance.
So, I wrote a proxy for the FMDB classes, which overrode -forwardInvocation: to perform -[NSInvocation invokeWithTarget:] on one specific thread, via -performSelector:onThread:withObject:waitUntilDone:. This solved the problem of too many calls to -[FMDatabase open], but -forwardInvocation: itself is rather expensive.
Is there a good way to solve this performance issue without rewriting all of the code that calls FMDB methods?
You’ve found the problem: don’t call
-performSelectorInBackground:withObject:! There’s no guarantee what it’ll do, but it probably won’t do the right thing.If what you want is a single “database thread” for background ops, then there are several options:
-performSelector:onThread:...instead.[[NSThread currentThread] threadDictionary]. This is a bit messy, since you have little control over when the database disappears. It also might violate the NSOperation contract (you’re supposed to return the thread to its original state when the operation finishes).