Here's an update for the commit rate tester for Mac OSX. With the original version, using fsync(), OSX doesn't do real syncs because the fsync call isn't properly implemented (my opinion). Apple took a shortcut with fsync and only flushes OS buffers to the drive, but the drive is then free to reorder the requests (that's okay) and execute them at a later time (that's not okay). You have to use fdcntl(F_FULLSYNC) to get data actually written to the platters. At least Apple does document this behavior. Here's the updated program:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #define MAX 3000 main () { int fd; int n; int loops; time_t elap; time_t start; if ((fd=open("big", O_RDWR+O_CREAT, 0777)) == -1) { perror("Error opening file"); exit(1); } start = time(NULL); for(loops=0; loops<MAX; loops++) { if (lseek(fd, 0, SEEK_SET) == -1) { perror("Error seeking file"); exit(1); } n = write(fd, &n, 1); if (n != 1) { perror("Error writing file"); exit(1); } #ifdef __APPLE__ fcntl(fd, F_FULLFSYNC); #else fsync(fd); #endif } elap = time(NULL)-start; printf("Time: %d seconds; TPS=%f\n", elap, MAX*1.0/elap); } With F_FULLSYNC, my G5 server and G4 laptop running 10.4 get these results: g5:~ mac$ ./sync Time: 174 seconds; TPS=17.241379 $ ./sync Time: 265 seconds; TPS=11.320755 The G5 is running a software RAID driver, so I thought that might be contributing to the awful performance, but the G4 laptop w/o RAID is even worse - I'm assuming because the drive rotational speed is probably 4200RPM instead of 7200RPM. These results are pretty horrible. The SQLite commit documentation says that Apple is doing a hard drive reset to implement the cache flush, which is why the performance is so bad. Maybe they have improved things with Leopard (10.5). Since SQLite does 3-4 syncs per commit, I was curious what the commit performance would be like in this environment. Here are the results with a Python test program and SQLite 3.6.14.2: import sqlite3 import time def runtest(path, sync): con = sqlite3.connect(path) con.execute('create table if not exists t (f)') con.execute('pragma synchronous=' + sync) con.execute('pragma fullsync=ON') con.execute('delete from t') con.commit() start = time.time() end = start+60 i = 0 n = 3000 while i < n and time.time() < end: con.execute("insert into t (f) values (?)", (i,)) con.commit() i += 1 elap = time.time() - start print "For pragma synchronous=", sync, "Time:", elap, "TPS:", n/elap con.close() path = "table" runtest(path, "off") runtest(path, "normal") runtest(path, "full") g5:~ mac$ Python-2.6.1/python.exe dbsync.py /Users/mac/Python-2.6.1/Lib/sqlite3/dbapi2.py:27: RuntimeWarning: Python C API version mismatch for module _sqlite3: This Python has API version 1013, module _sqlite3 has version 1012. from _sqlite3 import * For pragma synchronous= off Time: 1.97417807579 TPS: 1519.61975305 For pragma synchronous= normal Time: 4.06918787956 TPS: 737.247846202 For pragma synchronous= full Time: 4.78447008133 TPS: 627.028688445 Obviously, there's no way a 7200RPM drive can actually achieve these results. I'm building my own version of Python and sqlite here, and after some research, I think I didn't build sqlite with the -DHAVE_FULLFSYNC flag, so it isn't actually doing the fdcntl() call. Jim On 5/29/09, Jim Wilcoxson <pri...@gmail.com> wrote: > I agree that adding this to the library, and making it accessible via > a pragma command would be very useful. For example, pragma commitrate > 1000 would test the commit rate of 1000 commits and return the results > in transactions per second as a row. > > If I install my app on a client's machine, I could run this test > periodically to ensure that the system environment is going to support > "no corruption" operation, and/or send some kind of warning to my > customer that there is a risk of corruption because their system > environment has problems. > > If it were only an external program bundled with sqlite, I couldn't > really make use of it, because I'd have to distribute the program and > instructions how to use it, and rely on customers to actually do it. > > This is a pretty small function. Just for my own use, I'd consider > foreign key support to be way more bloated that this. > > Jim > > On 5/29/09, Marcus Grimm <mgr...@medcom-online.de> wrote: >>> On Thu, May 28, 2009 at 03:12:55PM -0700, Allen Fowler scratched on the >>> wall: >>>> >>>> > just for anybody who is interested: >>>> >>>> > >>>> > I translated Jim's function into window code and added >>>> > a page of 1024 that will be written, instead of a single byte. >>>> > On my Win-XP system I got 55 TPS, much faster than sqlite >>>> > seems to write a page but that might be related to the >>>> > additional overhead sqlite needs to do. >> >> just to add: I traced a little what sqlite does when an >> simple UPDATE is done within a transaction: It does >> two syncs on the journal file and one final sync on the >> db itselve, so achieving something like 15 TPS is reasonable. >> >> >>>> > >>>> > This brings me to a nice to have feature request: >>>> > How about adding similar test function in the sqlite API ? >>>> > This might use the vfs to write pages and gives some feedback >>>> > on the performance of the system where sqlite runs on. >>>> > It might also detect problems with the commit function... >>>> > Just an idea... >>>> > >>>> >>>> Interesting idea. >>> >>> It would make a lot more sense to make this an external utility >>> or an extension of the sqlite3 shell. Adding it to the core library >>> is a definite case of code bloat. >> >> Adding it into the API would allow my application to >> easily make the test for example the first time it runs >> on a system. But maybe a problem for the users that >> apply a sqlite wrapper. >> However, having it in sqlite3 shell would be very useful as >> well. >> >> Marcus >> >>> >>> Actually, a whole suite of performance related tests might be >>> interesting. >>> >>> -j >>> >>> -- >>> Jay A. Kreibich < J A Y @ K R E I B I.C H > >>> >>> "Our opponent is an alien starship packed with atomic bombs. We have >>> a protractor." "I'll go home and see if I can scrounge up a ruler >>> and a piece of string." --from Anathem by Neal Stephenson >>> _______________________________________________ >>> 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 >> > > > -- > Software first. Software lasts! > -- Software first. Software lasts! _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users