2005-04-23 12:18:39 UTC
Hi all.
Well, I finally got around to doing a (fairer) comparison between Derby and HSQLDB.
As promised, I altered the JDBCBench TPC-B test to set Derby in READ_UNCOMMITED mode (although I did not have the time yet to alter the TPC-B transaction details generation to ensure any ratio of conflicting reads/writes or anything like that).
Also as promised, I ran the following tests with various settings of WRITEDELAY for HSQLDB. With WRITEDELAY FALSE, the log is actually synched to disk upon each commit (each statement, in autocommit), With WRITEDELAY 1, it is synched at one second intervals, and so on.
As Fred mentions above, "Derby opens a random access file in a mode that is vaguely stated in the Javadoc published by Sun to save the changes to the disk as they occur"
And it was quite obvious to the ear (cruch, cruch) that HSQLDB WRITEDELAY FALSE is doing full (non-optimised) sych, whereas Derby is much quiter (so I'm assuming that Fred's observation is correct: Derby simply opens RAF with "rwd" (or "rws, perhaps).
This round of tests is on my Fedora Core II box at home, which
Anyway, here's Derby (10.0.2.1 release) embedded, using READ_UNCOMMITED isolation:
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.apache.derby.jdbc.EmbeddedDriver
URL:jdbc:derby:sampleDB
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 04:35:36 CST 2005
Initializing dataset...DBMS: Apache Derby
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 04:35:39 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 154.87 seconds.
Max/Min memory usage: 19148848 / 8843664 kb
0 / 2000 failed to complete.
Transaction rate: 12.914056950991153 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 138.105 seconds.
Max/Min memory usage: 14726648 / 7627216 kb
0 / 2000 failed to complete.
Transaction rate: 14.48173491184244 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 13.637 seconds.
Max/Min memory usage: 12078288 / 8290696 kb
0 / 2000 failed to complete.
Transaction rate: 146.65982254161472 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 10.616 seconds.
Max/Min memory usage: 10695912 / 7170528 kb
0 / 2000 failed to complete.
Transaction rate: 188.39487565938208 txn/sec.
Here's HSLQDB 1.8.0 (my repository copy from the dev1 CVS folder), using WRITEDELAY FALSE (and READ_UNCOMMITED, since the new TX work is not ready to benchmark):
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 04:48:26 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 04:48:28 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 17.576 seconds.
Max/Min memory usage: 8894344 / 6249800 kb
0 / 2000 failed to complete.
Transaction rate: 113.7915339098771 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 9.752 seconds.
Max/Min memory usage: 10294944 / 8040008 kb
0 / 2000 failed to complete.
Transaction rate: 205.08613617719442 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 12.835 seconds.
Max/Min memory usage: 8195120 / 6017320 kb
0 / 2000 failed to complete.
Transaction rate: 155.82391897156214 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 7.051 seconds.
Max/Min memory usage: 9695600 / 7652040 kb
0 / 2000 failed to complete.
Transaction rate: 283.6477095447454 txn/sec.
Certainly, these times are much closer (and to be fair, Derby's optimiser and bytecode generation for exection plan stuff likely has an overhead that cannot be adequately tested unless JDBC bench is modified yet again to allow doing multiple full runs without shutting down the system).
Here's HSQLDB 1.8.0 again, with WRITEDELAY 1
(yes: I've heard the argument that one can lose quite a bit of work in one second...but really, there's not many cases in OLTP where transactions have greater than vastly subsecond durations, and your're likely to lose far fewer if your transaction rate peaks out at 200/second...ha, ha...I mean if you sync to disk upon each commit...ok it's a trade off...If your app really dies badly, its likely because something terrible happend (power out, hardware failure, core dump, etc.), all of which are pretty unusual events in the overall scheme of things....most enterprise setups I've worked at or heard tell of promise no more than guaranteed durability of data up to the predeeding work day...i.e. restore to previous day from nightly diffs or restore from weekly full and then roll forward from nightly diffs upto the preceeding day):
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 05:09:54 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 05:09:57 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 5.829 seconds.
Max/Min memory usage: 8832464 / 6230480 kb
0 / 2000 failed to complete.
Transaction rate: 343.112026076514 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 3.523 seconds.
Max/Min memory usage: 10462480 / 8047328 kb
0 / 2000 failed to complete.
Transaction rate: 567.6979846721543 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 0.991 seconds.
Max/Min memory usage: 7724152 / 6041192 kb
0 / 2000 failed to complete.
Transaction rate: 2018.1634712411706 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 1.033 seconds.
Max/Min memory usage: 9698976 / 7689832 kb
0 / 2000 failed to complete.
Transaction rate: 1936.1084220716361 txn/sec.
Here's the result with WRITEDELAY 2
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 05:11:56 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 05:11:58 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 5.791 seconds.
Max/Min memory usage: 8877624 / 6270440 kb
0 / 2000 failed to complete.
Transaction rate: 345.36349507857017 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 3.545 seconds.
Max/Min memory usage: 10384264 / 8087880 kb
0 / 2000 failed to complete.
Transaction rate: 564.1748942172073 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 0.99 seconds.
Max/Min memory usage: 7690608 / 6042360 kb
0 / 2000 failed to complete.
Transaction rate: 2020.2020202020203 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 1.035 seconds.
Max/Min memory usage: 9705696 / 7702288 kb
0 / 2000 failed to complete.
Transaction rate: 1932.3671497584542 txn/sec.
Here's the result with WRITEDELAY 60
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 05:13:27 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 05:13:30 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 5.741 seconds.
Max/Min memory usage: 9147624 / 6475528 kb
0 / 2000 failed to complete.
Transaction rate: 348.3713638738896 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 3.624 seconds.
Max/Min memory usage: 10563032 / 8289552 kb
0 / 2000 failed to complete.
Transaction rate: 551.8763796909492 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 1.05 seconds.
Max/Min memory usage: 7991168 / 6046776 kb
0 / 2000 failed to complete.
Transaction rate: 1904.7619047619046 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 1.03 seconds.
Max/Min memory usage: 9807984 / 7730104 kb
0 / 2000 failed to complete.
Transaction rate: 1941.7475728155339 txn/sec.
Finally, just to make sure there aren't any other objections regarding settings that can be made (beyond this requires coding), here's HSQLDB with every performance reducing thing I can think of set toi the "worst" value:
#data lengths are checked and enforced for every row insert/update
sql.enforce_strict_size=true
# user "regular" rather than "nio" file access
hsqldb.nio_data_file=false
#reduce max number of allowed buffered rows to > 1K
hsqldb.cache_scale=8
# log is sync'ed for each commit:
WRITEDELAY FALSE
And here's the result:
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 05:18:07 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 05:18:15 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 19.358 seconds.
Max/Min memory usage: 4138616 / 1665264 kb
0 / 2000 failed to complete.
Transaction rate: 103.31645831180907 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 12.476 seconds.
Max/Min memory usage: 4036648 / 1961896 kb
0 / 2000 failed to complete.
Transaction rate: 160.30779095864057 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 16.092 seconds.
Max/Min memory usage: 2912608 / 1952336 kb
0 / 2000 failed to complete.
Transaction rate: 124.28535918468805 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 10.759 seconds.
Max/Min memory usage: 2838712 / 1862672 kb
0 / 2000 failed to complete.
Transaction rate: 185.89088205223533 txn/sec.
So, for prepared statements using multistatement transactions, comparing Derby in READUNCOMMITED isolation (to satisfy any previous objections concerning speed differences dues to enforcing better isolation) and HSQLDB with all known (speed) performance setting adjusted to most lower speed, we get essentially the same result:
Derby: Transaction rate: 188.39487565938208 txn/sec.
HSQLDB Transaction rate: 185.89088205223533 txn/sec.
I think we can safely ignore the 2.5 txn/sec difference, as I'm sure under multiple runs, that could go either way. Java is notorious for introducing noise well into the 2-5% range (due to hotspot effects, etc.), unless metrics are collected and averaged over multiple runs (allowing JVM to warm up) and usually only if each run consists of a large enough amount of work (unpredicatble thread switching overhead and the low precision of System.currentTimeMillis on very short duration runs adds a great deal of noise).
But what have we learned here?
Mostly, from what I can wager (based on the makup of a TPC-B transaction, which is very short and low volume), in this last case we have tested the speed at which the OS file sync command can operate, given the drive subsystem attached to my computer.
I did skim the Derby docs, looking for sections pretaining to control of logging characteristics. However, I did not find anything terribly promising here on a first pass.
But then Derby is open source, so I can crawl into the internals and interpose some logic to add WRITEDELAY functionality there to do better comparison (without the drive subsystem becoming the dominating factor for JDBCBench).
And maybe if I (find the time to) do that (you never know), it can be a patch and maybe even become an option for Derby users (choice is good...not everyone wanting to use an embedded database wants to be forced into <200 txn/sec rates when given the choice to trade this off against the generally miniscule risk of potentiallyf losing a small (one second) amount of work.
cache priming and setting initialPages, et. al. did look interesting (I'll play around with this as time allows, I guess).
Anyway, here's a last kick at the cat, doing the opposite of the last test (ensuring worst speed performance for HSQLDB).
In this test, I took the liberty of recompiling HSQLDB to open it's RAF data file in "rwd" mode.
And I reset the database properties to optional levels.
cache scale was set to 18 (default 12?)
nio file access set true
strict size set false
Here's the result:
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 06:13:05 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Drop old tables if they exist
Creates tables
Delete elements in table in case Drop didn't work
Using prepared statements
Insert data in branches table
Insert data in tellers table
Insert data in accounts table
10000 records inserted
20000 records inserted
30000 records inserted
40000 records inserted
50000 records inserted
60000 records inserted
70000 records inserted
80000 records inserted
90000 records inserted
100000 records inserted
done.
Complete: Sat Apr 23 06:13:10 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 4.707 seconds.
Max/Min memory usage: 38172400 / 34035336 kb
0 / 2000 failed to complete.
Transaction rate: 424.8990864669641 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 2.823 seconds.
Max/Min memory usage: 38781688 / 34562296 kb
0 / 2000 failed to complete.
Transaction rate: 708.4661707403471 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 0.482 seconds.
Max/Min memory usage: 37731744 / 35063600 kb
0 / 2000 failed to complete.
Transaction rate: 4149.377593360996 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 0.405 seconds.
Max/Min memory usage: 38206984 / 34883048 kb
0 / 2000 failed to complete.
Transaction rate: 4938.271604938272 txn/sec.
[root@localhost drivers]# sh ./jdbcbench-hsqldb-file.sh
*********************************************************
* JDBCBench v1.1 *
*********************************************************
Driver: org.hsqldb.jdbcDriver
URL:jdbc:hsqldb:file:jdbcbench/db
Scale factor value: 1
Number of clients: 2
Number of transactions per client: 1000
Transaction isolation: READ_UNCOMMITTED
Start: Sat Apr 23 06:13:45 CST 2005
Initializing dataset...DBMS: HSQL Database Engine
In transaction mode
Already initialized
done.
Complete: Sat Apr 23 06:13:47 CST 2005
* Starting Benchmark Run *
* Benchmark Report *
* Featuring <direct queries> <auto-commit>
--------------------
Time to execute 2000 transactions: 5.032 seconds.
Max/Min memory usage: 36467848 / 32491616 kb
0 / 2000 failed to complete.
Transaction rate: 397.456279809221 txn/sec.
* Benchmark Report *
* Featuring <direct queries> <transactions>
--------------------
Time to execute 2000 transactions: 2.8 seconds.
Max/Min memory usage: 37065000 / 33011704 kb
0 / 2000 failed to complete.
Transaction rate: 714.2857142857143 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <auto-commit>
--------------------
Time to execute 2000 transactions: 0.517 seconds.
Max/Min memory usage: 36720408 / 33509256 kb
0 / 2000 failed to complete.
Transaction rate: 3868.4719535783365 txn/sec.
* Benchmark Report *
* Featuring <prepared statements> <transactions>
--------------------
Time to execute 2000 transactions: 0.406 seconds.
Max/Min memory usage: 36787664 / 33474368 kb
0 / 2000 failed to complete.
Transaction rate: 4926.108374384236 txn/sec.
What would be quite interesting would be to offer HSQLDB users the choice to use the "rws" or "rwd" modes for the transaction log file.
Of course, this would require using a random access file for log file output, since there is no java API hook for setting "rws" or "rwd" mode for FileOutputStream.
But then HSQLDB could claim that it fully supports every bit as much a guarantee regarding log (and data file) write safety as Derby (but with far, far better speed performance in READ_UNCOMMITED mode, as demonstrated above).
Anyway, I'll promise here to put up another set of results after I have time to review and improve JDBCBench (or confirm it has been improved in the ways described in a post above) and after I have time to become familiar with how to properly tune Derby in terms of buffer managment to do semi-apples-to-apples settings on Derby regarding HSQLDB cache scale settings.
Bye for now,
Campbell