Hi,I'm trying to benchmark the offline storage engines on several browsers, and I'm observing some strange results when testing with chrome 21. Basically, I'm testing a few simple cases:- injecting data, one object injected per transaction- bulk-injecting data: 100 object injected per transaction- looking up objects.What I'm obrrserving, on the few computers I own:- on Linux, bulk-injection (ie, using one transaction to inject multiple object) is not better than using one separate transaction for each injected object. This is the strangest, because I absolutly didn't expect that.- On Windows, bulk injection seems fine, but lookup is super slow (it's slow on linux too, but not that slow).
I'm really puzzled by this, I checked my code twice, but I may be doing the things wrong with respect to transactions handling (I'm using setTimeout to yield).Are you guys observing the same strange behavior ? Or is there something obviously wrong in my code ?
The source code is there: https://github.com/reyesr/html5-storage-benchmarkThe benchmark test can be run on a github page: http://reyesr.github.com/html5-storage-benchmark/
I'm really puzzled by this, I checked my code twice, but I may be doing the things wrong with respect to transactions handling (I'm using setTimeout to yield).Are you guys observing the same strange behavior ? Or is there something obviously wrong in my code ?The source code is there: https://github.com/reyesr/html5-storage-benchmarkThe benchmark test can be run on a github page: http://reyesr.github.com/html5-storage-benchmark/
Nitty gritty details: In Chromium, the bulk of the time for IndexedDB spent doing IPC. You can see this by preparing your test, launching chrome://tracing in a second tab and starting recording, starting your test, then when complete switching back to the tracing tab to stop recording. When the analysis is complete you can see the IndexedDB calls which will be occuring in the Renderer thread and Browser's WebKit thread.
I don't have a hypothesis as to why lookups on Windows are particularly slow for you, but will look into it. Please do give Beta/Dev/Canary a try and see if those have better performance characteristics for you.
I was entirely not surprised by your finding as I assumed (like Josh) that so many other things dominate, that transactions might not make a noticable difference. Then I played with the benchmark. One thing that might be helpful is to show the rate (i.e. ops/second) or per-op time so you can compare apples-to-apples
I'm a little confused because for example when using Chrome Canary on my machine, I see 128ms for Inject-L (implying 2.5ms per put) and 939ms for InjectBulk-L (implying 0.4ms per put) - am I reading the numbers wrong? My interpretation (again, on Canary) implies that the "bulk" operations are 5x faster.
It's entirely possible that we managed to speed things up that much for this benchmark in Canary, but to be honest I'd be surprised if we sped it up by 5x!
Yes, that's what I get too, bulk-injection, with 100 puts per transaction (instead of 1 put per transaction for Inject-L), makes the performance ~5x faster. Note that this is not as much as the performance boost that bulk-injection provides with websql (which is more like x10 or x12).
It's entirely possible that we managed to speed things up that much for this benchmark in Canary, but to be honest I'd be surprised if we sped it up by 5x!Actually that's just the boost due to not creating a new transaction for each put, so that's not really unexpected AFAIK. However, I made some quick tests to compare the Chrome 22, Chrome 24 (Canary), and Firefox on the same WINDOWS laptop, this is what I roughly get:Chrome 22:- Inject-L: ~0.10 op/ms to 0.20 op/ms- InjectBulk-L: around 2.1 op/msChome 24 (Canary)- Inject-L: 0.10 to 0.20 op/ms- InjectBulk-L: around 1.3 op/msFrom this very quick test (I only ran the benchmark 6 times alternatively on chrome 22 and Canary, waiting a few seconds between each run) it seems on windows there's a performance drop for bulk-inject. But that's probably to be confirmed with tests on more computers.
--
You received this message because you are subscribed to the Google Groups "Chromium HTML5" group.
To post to this group, send email to chromiu...@chromium.org.
To unsubscribe from this group, send email to chromium-html...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-html5/?hl=en.
[FYI: below I am refering to "non-transactional requests" - what I mean is the pattern of having one or two requests per transaction, but lots of transactions, as opposed to a single transaction with lots of requests]I don't have a feel for how much transactional vs non-transactional performance improvement should be, but our goal is to (ultimately) be significantly faster than WebSQL for most operations, regardless of transaction granularity.
I think it's worth pointing out that the purpose of transactions is not for performance, but instead for correctness.We want to make sure that all operations in a given transaction are consistent with each other (meaning they all commit, or none of them do) and with other transactions (meaning that two "simultaneous" transactions to not have overlapping writes - all of one transaction writes, and then the other) - whatever the performance characteristics are given those goals just kind of fall out of these goals.
Very nice apples to apples comparison!My windows system gets the slow IDB lookup behavior with m22. I haven't run it with a local build yet.
I was surprised that the batch mode didn't help more in he websql case, but the numbers made more sense after noticing the batch size was only 100. I bumped it up to 2000 to further reduce the transaction overhead.
Also, while looking in websql-storage.js, I noticed in some cases test fixture completion was based on statement completion instead of transaction completion callbacks. That made me question the validity of the numbers because the last statement callback is invoked prior to the its containing transction being committed. So I shuffled some completion callbacks around to be based on xaction callbacks.
Hi Michael,Very nice apples to apples comparison!My windows system gets the slow IDB lookup behavior with m22. I haven't run it with a local build yet.Ho, so I'm not the only one... This is really strange, because I can't see any major difference between the two windows systems I used for my tests, the one with the slow lookups is an i7 with no ssd, and the laptop with normal lookups is an i5 with no ssd, both running windows 7.I was surprised that the batch mode didn't help more in he websql case, but the numbers made more sense after noticing the batch size was only 100. I bumped it up to 2000 to further reduce the transaction overhead.You're right, actually I did set a small batch size because when I initially used websql on an application to store some moderate amount of data, I had to tweak it as I observed some kind of hangup (probably a memory limit somewhere) when the transaction was too big (meaning: too many puts with too much data in them in a single transaction) on some browsers (I hope my memory does not fail me, but I think it was on the native Android 3 or 4 browser). It was like: browser silently failed when my batch size was 300 or 200, but was running fine with 150. So I set it at 100 just to be on the safe side, but you're right, this is suboptimal on desktop browsers. I should make some more tests and find a size closer to the limit for this benchmark.
Slices: | ||
---|---|---|
MessageLoop::RunTask | 22115.092 ms | 8262 occurrences |
IDBTransactionBackendImpl::taskEventTimerFired | 21789.476 ms | 1102 occurrences |
IDBTransactionBackendImpl::commit | 21787.412 ms | 1102 occurrences |
IDBLevelDBBackingStore::Transaction::begin | 1.615 ms | 1101 occurrences |
IDBTransactionBackendImpl::taskTimerFired | 135.913 ms | 1101 occurrences |
IDBObjectStoreBackendImpl::get | 4.68 ms | 1100 occurrences |
IDBLevelDBBackingStore::Transaction::commit | 21341.566 ms | 1102 occurrences |
IDBObjectStoreBackendImpl::getInternal | 129.083 ms | 1101 occurrences |
IDBLevelDBBackingStore::openObjectStoreCursor | 82.296 ms | 1101 occurrences |
IDBLevelDBBackingStore::getObjectStoreRecord | 22.06 ms | 1101 occurrences |
*Totals | 87409.193 ms | 18173 occurrences |
Selection start | 24279.595 ms | |
Selection extent | 24197.593 ms |
Hi Rodrigo,In release builds the really tall pole in the chrome://profiler data is a call to WebKitPlatformSupportImpl::DoTimeout in the browser process which really doesn't narrow it down very much.
Something you might want to do is to give a little breathing room between different tests. Some subsystems defer work so shortly after a flurry of activity against the api, the subsystem will wake up and finish things up. That finishing up could bleed over and color the results for a new flurry of activity against a different subsystem api that's being timed. LocalStorage is like that, changes are lazily committed to disk on a timer sometime after the api has returned from setting values. I believe IDB does compaction in the background.
In release builds the really tall pole in the chrome://profiler data is a call to WebKitPlatformSupportImpl::DoTimeout in the browser process which really doesn't narrow it down very much.Something you might want to do is to give a little breathing room between different tests. Some subsystems defer work so shortly after a flurry of activity against the api, the subsystem will wake up and finish things up. That finishing up could bleed over and color the results for a new flurry of activity against a different subsystem api that's being timed. LocalStorage is like that, changes are lazily committed to disk on a timer sometime after the api has returned from setting values. I believe IDB does compaction in the background.
Yup, the addition of the blue text below makes a monumental difference in read-only access. Where the Lookup2 test was taking ~70 seconds, it's now taking ~2 seconds!Really it'd be better to push a change like this all the way down into leveldb::DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch).bool LevelDBTransaction::commit(){ASSERT(!m_finished);if (m_tree.is_empty()) {m_finished = true;return true;}