The stack trace you've shown is a lock for allocating new page in page cache. It's probably the lock that helps SQLite ensure that total amount of consumed memory is not greater than the limit configured. But if you work only with in-memory databases then that check is moot and with next step SQLite goes into malloc to allocate new page. Most probably the standard malloc locks its mutex on entrance and so you'll get heavy contention on that lock anyway. So to resolve this problem first you should implement your own page cache, exclude inter-thread contention from there. And then if my guess above is correct then you'll need to implement your own memory allocator and exclude (or better to say lower as much as acceptable in your application) inter-thread contention from there. Page cache would be a relatively easy task (especially if you learn SQLite's own implementation first). Memory allocator -- not so much.
Pavel On Sunday, February 19, 2012, Chad Dombrova <chad...@gmail.com> wrote: > Hi all, > I need to insert a lot of data (a million+ rows) very quickly and it must occur on multiple threads. I do not have control over the creation and management of the threads, because I am using sqlite within the context of a plugin: I provide callback functions and the controlling process provides my functions with thread id's and other relevant data. > > I decided (perhaps naively) that the safest bet to avoid thread lock would be to have each thread insert into its own database (with its own db handle) during the heavy multi-threaded writing phase, then merge all the data into a single database file at the end. I am using the special ":memory:" database as that seemed ideal for my purposes: fast, private, and temporary. Everything works, but I am getting a lot of thread locking, so much so that running on 8 threads it is about 5 times slower than when it runs on a single thread. > > So my question is: if each thread is writing to its own database with its own connection, why are the threads locking? > > I've profiled it with Shark and the problem is definitely the mutex lock. Here is the callstack: > > sqlite3_step > sqlite3VdbeExec > sqlite3BtreeInsert > sqlite3BtreeMovetoUnpacked > getAndInitPage > sqlite3PcacheFetch > pcache3Fetch > pthreadMutexEnter > pthread_mutex_lock > > > All of the inserts for a thread are wrapped in a single BEGIN.. END. > > I'm setting: > > PRAGMA synchronous=OFF > PRAGMA journal_mode=OFF > > One peculiar thing is that I see no difference in behavior, stability, or performance when changing the sqlite3_open_v2() flags to include SQLITE_OPEN_NOMUTEX or SQLITE_OPEN_FULLMUTEX. > > The next step is to compile debug versions of everything and step through to find out what is causing the lock, but before I go down that road, I'd like to know if there isn't something else I should try first. > > I'm using the sqlite that comes with osx 10.6, version 3.6.12. > > thanks, > chad > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users