Keith, I understand your point. The timescale of polling is between 1 and 10 seconds by sleep loop depending on operational objectives. This range of sleep loop will have a corresponding latency of between 0.5 and 5 seconds for single commands with a uniform arrival time distribution.
The idea was to get near the 0.5 second latency of the 1 second sleep loop while actually polling in a very gentle 10 second sleep loop. Thanks for the colorful explanation of custom busy handlers. On Sat, Mar 25, 2017 at 11:17 PM, Keith Medcalf <kmedc...@dessus.com> wrote: > Saturday, 25 March, 2017 23:44. petern <peter.nichvolo...@gmail.com> > wrote: > > > Can anybody explain the purpose of > > http://sqlite.org/c3ref/busy_handler.html > > ? It seems the only practical use would be to allow the caller to give > > the engine a suggested lock deadline before SQLITE_BUSY is returned by > > sqlite3_exec or sqlite3_step Then, if the calling thread would prefer > to > > wait longer, it can just retry with progressively smaller lock deadline > > until it's time to do something else. > > The busy handler is used if you have set a timeout to obtain a lock. If > you try to do > > BEGIN IMMEDIATE > > on a database that is not in WAL mode, then in order to obtain a lock > there must be no active readers or writers. If there are, the lock cannot > be obtained an SQLITE_BUSY is returned and you try again later. If you set > a timeout with PRAMGA timeout, that specifies the amount of time to wait > for a lock before returning SQLITE_BUSY. The busy handler is used to > "handle" the "busy" state (that is, rather than return SQLITE_BUSY to the > caller, your busy handler is called. You do something (like wait a while > using sleep, then return, perhaps displaying flying ball bearings or other > annoyances to indicate to the user that the program is waiting). Lather > rinse repeat until the specified timeout expires at which time SQLITE_BUSY > is returned to the caller. > > If you do not specify your own custom busy handler (to display flying ball > bearings, etc, or do your own exponential sleeping, etc) then the default > busy_handler is used. The default busy handler does its own exponential > backoff algorithm but does not display whirling ball bearings or anything > else, it just sleeps silently. > > > In my application it is more ideal if commands in the command table are > > known to the readers immediately but without the overhead of rapid > polling > > by the readers. Setting a suggested wait time and then waiting again if > > SQLITE_BUSY comes back early and there's nothing else to do would be just > > fine. > > Again, you have specified "RAPID POLLING". Can you please define what you > mean by "RAPID POLLING"? To me, "RAPID POLLING" means using the immensely > stupid spinlock type implementation such as: > > open connection > while (nothing to do) > query database for something to do > do what needs doing > > If you need things to go "RAPIDLY" then you need to use some IPC > notification mechanism. > > Please state in explicit terms your definition of "RAPIDLY". Using terms > without defining them makes it difficult for anyone to understand what you > are talking about. One persons "RAPIDLY" may mean "after the MoC is filled > out and endorsed, operations windows are arranged, and the board operator > gives the final go ahead -- in other words, two weeks to six months". > Another person's definition of "RAPIDLY" may be "within 250 milliseconds". > Please specify what you definition of "RAPIDLY" is, giving minimum and > maximum bounds in common time units. > > If RAPIDLY means "in less than one second, 33% of the time, within two > seconds 75% of the time, and no more than three seconds ever" then you are > talking about rather SLOW POLLING. > > open connection > while (nothing to do) > sleep 1 second > query database for something to do > do what needs doing > > This type of SLOW POLLING will use about 1% of the available CPU on a 4.77 > Mhz 8086 CPU while in the polling loop. This means that you can have about > 100 such processes polling at the same time on a 4.77 Mhz 8086 equipped > computer. On a modern CPU with a couple of cores and about 2Ghz per code, > you should be able to run many tens of thousands of such processes > simultaneously and STILL have resources left over. (though the OS > scheduler will probably consume more CPU than the polling loops do, and the > process table and OS resources are likely to become exhausted long before > you hit any reasonable limit on the resource limits for the simultaneously > polling processes themselves.) > > > [Regarding the suggestion of synchronizing the readers with another > > concurrency object, I could do that. But if the database connection > > itself > > can coordinate the same thing, the reader program is a lot simpler and > > more > > portable.] > > > I'm not sure I understand Simon's comments how using EXCLUSIVE > TRANSACTION > > writer isolation is subverting something subject to change if that > > isolation level is desired. Reader would still be querying the command > > table but in committed read mode with EXCLUSIVE isolation. Why would > this > > work differently on different systems? From > > http://www.sqlite.org/lockingv3.html > > > "EXCLUSIVE An EXCLUSIVE lock is needed in order to write to the > > database file. Only one EXCLUSIVE lock is allowed on the file and no > other > > locks of any kind are allowed to coexist with an EXCLUSIVE lock. In order > > to maximize concurrency, SQLite works to minimize the amount of time that > > EXCLUSIVE locks are held." > > > "If the same database is being read and written using two different > > database > > connections <http://sqlite.org/c3ref/sqlite3.html> (two different > sqlite3 > > <http://sqlite.org/c3ref/sqlite3.html> objects returned by separate > calls > > to sqlite3_open() <http://sqlite.org/c3ref/open.html>) and the two > > database > > connections do not have a shared cache > > <http://sqlite.org/sharedcache.html>, > > then the reader is only able to see complete committed transactions from > > the writer." > > > "The previous paragraph is also true (separate database connections are > > isolated from one another) in shared cache mode > > <http://sqlite.org/sharedcache.html> as long as the read_uncommitted > > pragma > > <http://sqlite.org/pragma.html#pragma_read_uncommitted> remains turned > > off. > > The read_uncommitted pragma > > <http://sqlite.org/pragma.html#pragma_read_uncommitted> is off by > default" > > > On Sat, Mar 25, 2017 at 7:56 PM, Simon Slavin <slav...@bigfraud.org> > > wrote: > > > > > > > > On 26 Mar 2017, at 2:35am, petern <peter.nichvolo...@gmail.com> wrote: > > > > > > > Is there something that can be done by the writer, like holding a > > BEGIN > > > > EXCLUSIVE TRANSACTION open with PRAGMA read_uncommitted=0? Would > that > > > > block all readers or would they continue to get empty results from > the > > > > command table? I suppose I could start experimenting with this but > it > > > > would be faster to get some hints from experts on his forum. > > > > > > The problem is that you can’t monitor the connection to the database > > which > > > does the writing. The connection you’re using to do the reading > doesn’t > > > know anything special about what another connection is doing. > > > > > > I can think of ways to make SQLite be slightly more helpful than > vanilla > > > SQL would be. For instance, you could use a separate file for your > > "cmd" > > > table and use > > > > > > <https://sqlite.org/pragma.html#pragma_data_version> > > > > > > PRAGMA data_version; > > > > > > to see whether any modifications at all had been done. But when you > > > figure out what you’ll actually be doing in your program, you’re still > > > executing a command and analyzing the result. And it has the > > disadvantage > > > that it’s terribly non-standard and someone reading your code won’t > > > understand it. > > > > > > I suspect that you’re better off just sticking to standard calls. > > > > > > > If a writer TRANSACTION might work, I'd be interested to know the > > minimum > > > > transaction and isolation settings that would cause readers to block > > in > > > an > > > > example of reader using sqlite3_busy_handler with the sqlite3_exec > > call > > > in > > > > a single threaded program to achieve PRAGMA busy_timeout=N. > > > > > > I recommend that you don’t try to mess with the mutex at this level. > > > Detailed behaviour of the mutex can vary a lot depending on precise > > > versions of OS, FS, storage, etc.. You could develop something which > > > worked very well on your programming computer, then find it completely > > > misses updates on another computer, or even when you just update your > OS > > or > > > replace your hard disk. Your method of storing commands in a table and > > > using conventional SQL to read them should work fine. > > > > > > > Comments on the benefits of WAL mode for this pattern would also be > > > helpful > > > > considering there is one writer that needs speedy access to > > potentially > > > > large number of of changes before the writer transaction finally > > inserts > > > > some new commands and closes the transaction for the readers to see > > the > > > > updated command table. > > > > > > Don’t try to subvert transactions to act as a mutex. You might end up > > > depending on something which stops working in a later version of > SQLite. > > > > > > Try both WAL and original modes. See which one gives you acceptable > > > behaviour. Pick that one. > > > > > > Another way to do it would be to add a "done" column to your "cmd" > table > > > containing either 0 or 1. When the command is added to the table this > > > defaults to 0. Your loop reads all rows which have this set to zero. > > You > > > then execute those commands and use an UPDATE to set the "done" column > > to 1 > > > for those rows. This means you don’t care about rowid, and are > > > better-protected against crashes. But I think the method you described > > > originally may be better than this. > > > > > > Simon. > > > _______________________________________________ > > > sqlite-users mailing list > > > sqlite-users@mailinglists.sqlite.org > > > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > > > > > _______________________________________________ > > sqlite-users mailing list > > sqlite-users@mailinglists.sqlite.org > > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users