{"action":"created","issue":{"url":"https://api.github.com/repos/jsampson/prevayler/issues/12","labels_url":"https://api.github.com/repos/jsampson/prevayler/issues/12/labels{/name}","comments_url":"https://api.github.com/repos/jsampson/prevayler/issues/12/comments","events_url":"https://api.github.com/repos/jsampson/prevayler/issues/12/events","html_url":"https://github.com/jsampson/prevayler/pull/12","id":116889047,"number":12,"title":"Preallocate journal file space. Avoid writing metadata on every sync.","user":{"login":"shvachko","id":11998604,"avatar_url":"https://avatars.githubusercontent.com/u/11998604?v=3","gravatar_id":"","url":"https://api.github.com/users/shvachko","html_url":"https://github.com/shvachko","followers_url":"https://api.github.com/users/shvachko/followers","following_url":"https://api.github.com/users/shvachko/following{/other_user}","gists_url":"https://api.github.com/users/shvachko/gists{/gist_id}","starred_url":"https://api.github.com/users/shvachko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shvachko/subscriptions","organizations_url":"https://api.github.com/users/shvachko/orgs","repos_url":"https://api.github.com/users/shvachko/repos","events_url":"https://api.github.com/users/shvachko/events{/privacy}","received_events_url":"https://api.github.com/users/shvachko/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-11-14T02:29:11Z","updated_at":"2015-11-14T02:29:51Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/jsampson/prevayler/pulls/12","html_url":"https://github.com/jsampson/prevayler/pull/12","diff_url":"https://github.com/jsampson/prevayler/pull/12.diff","patch_url":"https://github.com/jsampson/prevayler/pull/12.patch"},"body":"Hey guys.\r\nI am new here, but WANdisco was using Prevayler in production for quite a while.\r\nI thought you may find my patch interesting, as it increases Prevayler's performs 2x."},"comment":{"url":"https://api.github.com/repos/jsampson/prevayler/issues/comments/156611741","html_url":"https://github.com/jsampson/prevayler/pull/12#issuecomment-156611741","issue_url":"https://api.github.com/repos/jsampson/prevayler/issues/12","id":156611741,"user":{"login":"shvachko","id":11998604,"avatar_url":"https://avatars.githubusercontent.com/u/11998604?v=3","gravatar_id":"","url":"https://api.github.com/users/shvachko","html_url":"https://github.com/shvachko","followers_url":"https://api.github.com/users/shvachko/followers","following_url":"https://api.github.com/users/shvachko/following{/other_user}","gists_url":"https://api.github.com/users/shvachko/gists{/gist_id}","starred_url":"https://api.github.com/users/shvachko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shvachko/subscriptions","organizations_url":"https://api.github.com/users/shvachko/orgs","repos_url":"https://api.github.com/users/shvachko/repos","events_url":"https://api.github.com/users/shvachko/events{/privacy}","received_events_url":"https://api.github.com/users/shvachko/received_events","type":"User","site_admin":false},"created_at":"2015-11-14T02:29:51Z","updated_at":"2015-11-14T02:29:51Z","body":"Here is more details:\r\n\r\nI was comparing Prevayler's performance with HDFS NameNode EditsLog. The two systems serve the same purpose, that is journalling transactions. And my assumption was that besides all the differences in implementation details, if I put enough load on either of them to make them i/o bound, the performance should be roughly the same. Unless of course something is going wrong with one of the systems.\r\n\r\nIn a nutshell, my benchmarks showed that Prevayler's throughput (tx/sec) is two times lower than that of a NameNode. After some digging I realized that the main reason for that is that NameNode does not write metadata on every sync, only the data. This is done by using\r\n`FileChannel.force(false)`\r\ninstead of\r\n`FileDescriptor.sync()`\r\nThe latter is used in `DurableOutputStream.waitUntilSynced()`, and it syncs both data and metadata, causing two IOs instead of one as in `force(false)`.\r\nIn general one wants to save file metadata when new data is appended to a file. But if the disk space for the journal file is preallocated in advance then there is no need to save metadata frequently, as file size is not changing. This is another difference that NameNode's EditsLog has compared to Prevayler.\r\n\r\nFor benchmarking I used `NNThroughputBenchmark`, which is a standard tool in HDFS, and which measures the throughput of different NameNode operations excluding any network overhead (no RPCs). I wrote a similar `PrevaylerBenchmark`, which uses a map as a prevalent system, and adds key-value pairs into it as transactions. The benchmark allows to run multiple update threads. Here are some results comparing Prevayler with NameNode before and after my changes:\r\n\r\no | Threads | #Ops | Throughput Ops/sec | Elapsed time sec\r\n--- | ---------- | ------ | ------------------------- | ----------------------\r\nPrevayler | 1 | 5000 | 40.486 | 123.498\r\nNameNode | 1 | 5000 | 77.438 | 64.568\r\nPrevayler | 512 | 1,000,000 | 9439.929 | 105.933\r\nNameNode | 512 | 1,000,000 | 13306.0116 | 64.568\r\n\r\nAfter the patch:\r\n\r\no | Threads | #Ops | Throughput Ops/sec | Elapsed time sec\r\n--- | ---------- | ------ | ------------------------- | ----------------------\r\nPrevayler | 1 | 5000 | **81.904** | 61.047\r\nNameNode | 1 | 5000 | 77.438 | 64.568\r\nPrevayler | 512 | 1,000,000 | **16230.604** | 61.612\r\nNameNode | 512 | 1,000,000 | 13306.0116 | 64.568\r\n\r\nThe patch contains `PrevaylerBenchmark` and changes to syncing and preallocation.\r\nPlease take a look."}}