higgs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. data/ChangeLog +208 -0
  2. data/LICENSE +26 -0
  3. data/README +2 -0
  4. data/Rakefile +75 -0
  5. data/bin/higgs_backup +67 -0
  6. data/bin/higgs_dump_index +43 -0
  7. data/bin/higgs_dump_jlog +42 -0
  8. data/bin/higgs_verify +37 -0
  9. data/lib/cgi/session/higgs.rb +72 -0
  10. data/lib/higgs/block.rb +192 -0
  11. data/lib/higgs/cache.rb +117 -0
  12. data/lib/higgs/dbm.rb +55 -0
  13. data/lib/higgs/exceptions.rb +31 -0
  14. data/lib/higgs/flock.rb +77 -0
  15. data/lib/higgs/index.rb +164 -0
  16. data/lib/higgs/jlog.rb +159 -0
  17. data/lib/higgs/lock.rb +189 -0
  18. data/lib/higgs/storage.rb +1086 -0
  19. data/lib/higgs/store.rb +228 -0
  20. data/lib/higgs/tar.rb +390 -0
  21. data/lib/higgs/thread.rb +370 -0
  22. data/lib/higgs/tman.rb +513 -0
  23. data/lib/higgs/utils/bman.rb +285 -0
  24. data/lib/higgs/utils.rb +22 -0
  25. data/lib/higgs/version.rb +21 -0
  26. data/lib/higgs.rb +59 -0
  27. data/misc/cache_bench/cache_bench.rb +43 -0
  28. data/misc/dbm_bench/.strc +8 -0
  29. data/misc/dbm_bench/Rakefile +78 -0
  30. data/misc/dbm_bench/dbm_multi_thread.rb +199 -0
  31. data/misc/dbm_bench/dbm_rnd_delete.rb +43 -0
  32. data/misc/dbm_bench/dbm_rnd_read.rb +44 -0
  33. data/misc/dbm_bench/dbm_rnd_update.rb +44 -0
  34. data/misc/dbm_bench/dbm_seq_read.rb +45 -0
  35. data/misc/dbm_bench/dbm_seq_write.rb +44 -0
  36. data/misc/dbm_bench/st_verify.rb +28 -0
  37. data/misc/io_bench/cksum_bench.rb +48 -0
  38. data/misc/io_bench/jlog_bench.rb +71 -0
  39. data/misc/io_bench/write_bench.rb +128 -0
  40. data/misc/thread_bench/lock_bench.rb +132 -0
  41. data/mkrdoc.rb +8 -0
  42. data/rdoc.yml +13 -0
  43. data/sample/count.rb +60 -0
  44. data/sample/dbmtest.rb +38 -0
  45. data/test/Rakefile +45 -0
  46. data/test/run.rb +32 -0
  47. data/test/test_block.rb +163 -0
  48. data/test/test_cache.rb +214 -0
  49. data/test/test_cgi_session.rb +142 -0
  50. data/test/test_flock.rb +162 -0
  51. data/test/test_index.rb +258 -0
  52. data/test/test_jlog.rb +180 -0
  53. data/test/test_lock.rb +320 -0
  54. data/test/test_online_backup.rb +169 -0
  55. data/test/test_storage.rb +439 -0
  56. data/test/test_storage_conf.rb +202 -0
  57. data/test/test_storage_init_opts.rb +89 -0
  58. data/test/test_store.rb +211 -0
  59. data/test/test_tar.rb +432 -0
  60. data/test/test_thread.rb +541 -0
  61. data/test/test_tman.rb +875 -0
  62. data/test/test_tman_init_opts.rb +56 -0
  63. data/test/test_utils_bman.rb +234 -0
  64. metadata +115 -0
@@ -0,0 +1,199 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: dbm_multi_thread.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/dbm'
10
+ require 'higgs/lock'
11
+ require 'higgs/thread'
12
+ require 'thread'
13
+
14
+ loop_count = (ARGV.shift || '100').to_i
15
+ transaction_count = (ARGV.shift || '100').to_i
16
+ thread_count = (ARGV.shift || '10').to_i
17
+ puts "#{$0}: LOOP:#{loop_count}, TRANSACTION:#{transaction_count}, THREAD:#{thread_count}"
18
+ puts ''
19
+
20
+ name = File.join(File.dirname($0), 'foo')
21
+ conf_path = File.join(File.dirname($0), '.strc')
22
+
23
+ options = {}
24
+ options.update(Higgs::Storage.load_conf(conf_path)) if (File.exist? conf_path)
25
+
26
+ [ Higgs::GiantLockManager.new,
27
+ Higgs::FineGrainLockManager.new
28
+ ].each do |lock_manager|
29
+ puts lock_manager.class
30
+ options[:lock_manager] = lock_manager
31
+ Higgs::DBM.open(name, options) {|dbm|
32
+ dbm.transaction{|tx|
33
+ tx[:foo] = 'a'
34
+ thread_count.times do |i|
35
+ tx[i] = i.to_s
36
+ end
37
+ }
38
+
39
+ Benchmark.bm(16) do |x|
40
+ x.report(' read') {
41
+ (thread_count * transaction_count).times do
42
+ dbm.transaction(true) {|tx|
43
+ loop_count.times do
44
+ tx[:foo]
45
+ end
46
+ }
47
+ end
48
+ }
49
+
50
+ barrier = Higgs::Barrier.new(thread_count + 1)
51
+ th_grp = ThreadGroup.new
52
+ thread_count.times do
53
+ th_grp.add Thread.new{
54
+ barrier.wait
55
+ transaction_count.times do
56
+ dbm.transaction(true) {|tx|
57
+ loop_count.times do
58
+ tx[:foo]
59
+ end
60
+ }
61
+ end
62
+ }
63
+ end
64
+
65
+ x.report('MT read') {
66
+ barrier.wait
67
+ for th in th_grp.list
68
+ th.join
69
+ end
70
+ }
71
+
72
+ x.report(' write') {
73
+ (thread_count * transaction_count).times do
74
+ dbm.transaction{|tx|
75
+ loop_count.times do
76
+ tx[:foo] = 'a'
77
+ end
78
+ }
79
+ end
80
+ }
81
+
82
+ barrier = Higgs::Barrier.new(thread_count + 1)
83
+ th_grp = ThreadGroup.new
84
+ thread_count.times do
85
+ th_grp.add Thread.new{
86
+ barrier.wait
87
+ transaction_count.times do
88
+ dbm.transaction{|tx|
89
+ loop_count.times do
90
+ tx[:foo] = 'a'
91
+ end
92
+ }
93
+ end
94
+ }
95
+ end
96
+
97
+ x.report('MT write') {
98
+ barrier.wait
99
+ for th in th_grp.list
100
+ th.join
101
+ end
102
+ }
103
+
104
+ x.report(' sparse write') {
105
+ thread_count.times do |i|
106
+ key = i
107
+ value = i.to_s
108
+ transaction_count.times do
109
+ dbm.transaction{|tx|
110
+ loop_count.times do
111
+ tx[key] = value
112
+ end
113
+ }
114
+ end
115
+ end
116
+ }
117
+
118
+ barrier = Higgs::Barrier.new(thread_count + 1)
119
+ th_grp = ThreadGroup.new
120
+ thread_count.times do |i|
121
+ key = i
122
+ value = i.to_s
123
+ th_grp.add Thread.new{
124
+ barrier.wait
125
+ transaction_count.times do
126
+ dbm.transaction{|tx|
127
+ loop_count.times do
128
+ tx[key] = value
129
+ end
130
+ }
131
+ end
132
+ }
133
+ end
134
+
135
+ x.report('MT sparse write') {
136
+ barrier.wait
137
+ for th in th_grp.list
138
+ th.join
139
+ end
140
+ }
141
+
142
+ x.report(' read/write') {
143
+ ((thread_count - 1) * transaction_count).times do
144
+ dbm.transaction(true) {|tx|
145
+ loop_count.times do
146
+ tx[:foo]
147
+ end
148
+ }
149
+ end
150
+ transaction_count.times do
151
+ dbm.transaction{|tx|
152
+ loop_count.times do
153
+ tx[:foo] = 'a'
154
+ end
155
+ }
156
+ end
157
+ }
158
+
159
+ barrier = Higgs::Barrier.new(thread_count + 1)
160
+ th_grp = ThreadGroup.new
161
+ (thread_count - 1).times do
162
+ th_grp.add Thread.new{
163
+ barrier.wait
164
+ transaction_count.times do
165
+ dbm.transaction(true) {|tx|
166
+ loop_count.times do
167
+ tx[:foo]
168
+ end
169
+ }
170
+ end
171
+ }
172
+ end
173
+ th_grp.add Thread.new{
174
+ barrier.wait
175
+ transaction_count.times do
176
+ dbm.transaction{|tx|
177
+ loop_count.times do
178
+ tx[:foo] = 'a'
179
+ end
180
+ }
181
+ end
182
+ }
183
+
184
+ x.report('MT read/write') {
185
+ barrier.wait
186
+ for th in th_grp.list
187
+ th.join
188
+ end
189
+ }
190
+ end
191
+
192
+ puts ''
193
+ }
194
+ end
195
+
196
+ # Local Variables:
197
+ # mode: Ruby
198
+ # indent-tabs-mode: nil
199
+ # End:
@@ -0,0 +1,43 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: dbm_rnd_delete.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/dbm'
10
+
11
+ loop_count = (ARGV.shift || '100').to_i
12
+ data_count = (ARGV.shift || '10').to_i
13
+ puts "#{$0}: LOOP:#{loop_count}, DATA:#{data_count}"
14
+
15
+ name = File.join(File.dirname($0), 'foo')
16
+ conf_path = File.join(File.dirname($0), '.strc')
17
+
18
+ options = {}
19
+ options.update(Higgs::Storage.load_conf(conf_path)) if (File.exist? conf_path)
20
+
21
+ Higgs::DBM.open(name, options) {|dbm|
22
+ srand(0)
23
+ key_list = dbm.transaction{|tx| tx.keys }
24
+
25
+ Benchmark.bm do |x|
26
+ x.report('dbm rnd delete:') {
27
+ loop_count.times do
28
+ dbm.transaction{|tx|
29
+ data_count.times do
30
+ k = key_list[rand(key_list.length)]
31
+ tx.delete(k)
32
+ end
33
+ }
34
+ end
35
+ }
36
+ end
37
+ print "\n"
38
+ }
39
+
40
+ # Local Variables:
41
+ # mode: Ruby
42
+ # indent-tabs-mode: nil
43
+ # End:
@@ -0,0 +1,44 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: dbm_rnd_read.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/dbm'
10
+
11
+ loop_count = (ARGV.shift || '100').to_i
12
+ data_count = (ARGV.shift || '10').to_i
13
+ puts "#{$0}: LOOP:#{loop_count}, DATA:#{data_count}"
14
+
15
+ name = File.join(File.dirname($0), 'foo')
16
+ conf_path = File.join(File.dirname($0), '.strc')
17
+
18
+ options = {}
19
+ options.update(Higgs::Storage.load_conf(conf_path)) if (File.exist? conf_path)
20
+ options[:read_only] = true
21
+
22
+ Higgs::DBM.open(name, options) {|dbm|
23
+ srand(0)
24
+ key_list = dbm.transaction{|tx| tx.keys }
25
+
26
+ Benchmark.bm do |x|
27
+ x.report('dbm rnd read:') {
28
+ loop_count.times do
29
+ dbm.transaction{|tx|
30
+ data_count.times do
31
+ k = key_list[rand(key_list.length)]
32
+ tx[k]
33
+ end
34
+ }
35
+ end
36
+ }
37
+ end
38
+ print "\n"
39
+ }
40
+
41
+ # Local Variables:
42
+ # mode: Ruby
43
+ # indent-tabs-mode: nil
44
+ # End:
@@ -0,0 +1,44 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: dbm_rnd_update.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/dbm'
10
+
11
+ loop_count = (ARGV.shift || '100').to_i
12
+ data_count = (ARGV.shift || '10').to_i
13
+ max_dat_len = (ARGV.shift || '32768').to_i
14
+ puts "#{$0}: LOOP:#{loop_count}, DATA:#{data_count}, MAX_DAT_LEN:#{max_dat_len}"
15
+
16
+ name = File.join(File.dirname($0), 'foo')
17
+ conf_path = File.join(File.dirname($0), '.strc')
18
+
19
+ options = {}
20
+ options.update(Higgs::Storage.load_conf(conf_path)) if (File.exist? conf_path)
21
+
22
+ Higgs::DBM.open(name, options) {|dbm|
23
+ srand(0)
24
+ key_list = dbm.transaction{|tx| tx.keys }
25
+
26
+ Benchmark.bm do |x|
27
+ x.report('dbm rnd update:') {
28
+ loop_count.times do
29
+ dbm.transaction{|tx|
30
+ data_count.times do
31
+ k = key_list[rand(key_list.length)]
32
+ tx[k] = 0xFF.chr * (rand(max_dat_len))
33
+ end
34
+ }
35
+ end
36
+ }
37
+ end
38
+ print "\n"
39
+ }
40
+
41
+ # Local Variables:
42
+ # mode: Ruby
43
+ # indent-tabs-mode: nil
44
+ # End:
@@ -0,0 +1,45 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: dbm_seq_read.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/dbm'
10
+
11
+ loop_count = (ARGV.shift || '100').to_i
12
+ data_count = (ARGV.shift || '10').to_i
13
+ puts "#{$0}: LOOP:#{loop_count}, DATA:#{data_count}"
14
+
15
+ name = File.join(File.dirname($0), 'foo')
16
+ conf_path = File.join(File.dirname($0), '.strc')
17
+
18
+ options = {}
19
+ options.update(Higgs::Storage.load_conf(conf_path)) if (File.exist? conf_path)
20
+ options[:read_only] = true
21
+
22
+ Higgs::DBM.open(name, options) {|dbm|
23
+ key_list = dbm.transaction{|tx|
24
+ tx.keys.map{|k| k.to_i }.sort.map{|i| i.to_s }
25
+ }
26
+
27
+ Benchmark.bm do |x|
28
+ x.report('dbm seq read:') {
29
+ loop_count.times do |i|
30
+ dbm.transaction{|tx|
31
+ data_count.times do |j|
32
+ k = key_list[(i + j) % key_list.length]
33
+ tx[k]
34
+ end
35
+ }
36
+ end
37
+ }
38
+ end
39
+ print "\n"
40
+ }
41
+
42
+ # Local Variables:
43
+ # mode: Ruby
44
+ # indent-tabs-mode: nil
45
+ # End:
@@ -0,0 +1,44 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: dbm_seq_write.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/dbm'
10
+
11
+ loop_count = (ARGV.shift || '100').to_i
12
+ data_count = (ARGV.shift || '10').to_i
13
+ max_dat_len = (ARGV.shift || '32768').to_i
14
+ puts "#{$0}: LOOP:#{loop_count}, DATA:#{data_count}, MAX_DAT_LEN:#{max_dat_len}"
15
+
16
+ name = File.join(File.dirname($0), 'foo')
17
+ conf_path = File.join(File.dirname($0), '.strc')
18
+
19
+ options = {}
20
+ options.update(Higgs::Storage.load_conf(conf_path)) if (File.exist? conf_path)
21
+
22
+ Higgs::DBM.open(name, options) {|dbm|
23
+ srand(0)
24
+
25
+ Benchmark.bm do |x|
26
+ x.report('dbm seq write:') {
27
+ loop_count.times do |i|
28
+ dbm.transaction{|tx|
29
+ data_count.times do |j|
30
+ k = (i * data_count + j).to_s
31
+ d = 0xFF.chr * (rand(max_dat_len))
32
+ tx[k] = d
33
+ end
34
+ }
35
+ end
36
+ }
37
+ end
38
+ print "\n"
39
+ }
40
+
41
+ # Local Variables:
42
+ # mode: Ruby
43
+ # indent-tabs-mode: nil
44
+ # End:
@@ -0,0 +1,28 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for ident(1)
4
+ CVS_ID = '$Id: st_verify.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'higgs/storage'
10
+
11
+ puts $0
12
+
13
+ st = Higgs::Storage.new('foo', :read_only => true)
14
+ begin
15
+ Benchmark.bm do |x|
16
+ x.report('st verify') {
17
+ st.verify
18
+ }
19
+ end
20
+ print "\n"
21
+ ensure
22
+ st.shutdown
23
+ end
24
+
25
+ # Local Variables:
26
+ # mode: Ruby
27
+ # indent-tabs-mode: nil
28
+ # End:
@@ -0,0 +1,48 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for dient(1)
4
+ CVS_ID = '$Id: cksum_bench.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ require 'benchmark'
7
+ require 'digest/md5'
8
+ require 'digest/rmd160'
9
+ require 'digest/sha1'
10
+ require 'digest/sha2'
11
+
12
+ count = (ARGV.shift || '10000').to_i
13
+ size = (ARGV.shift || '65536').to_i
14
+ puts "#{$0}: COUNT:#{count}, SIZE:#{size}"
15
+
16
+ data = 0xFF.chr * size
17
+
18
+ task_list = [ 8, 16, 32, 64, 128 ].map{|n|
19
+ [ "String\#sum(#{n}):",
20
+ proc{
21
+ count.times do
22
+ data.sum(n)
23
+ end
24
+ }
25
+ ]
26
+ } + [
27
+ Digest::MD5, Digest::RMD160,
28
+ Digest::SHA1, Digest::SHA256, Digest::SHA384, Digest::SHA512
29
+ ].map{|d|
30
+ [ "#{d}:",
31
+ proc{
32
+ count.times do
33
+ d.digest(data)
34
+ end
35
+ }
36
+ ]
37
+ }
38
+
39
+ Benchmark.bm(task_list.map{|n, t| n.length }.max) do |x|
40
+ task_list.each do |name, task|
41
+ x.report(name) { task.call }
42
+ end
43
+ end
44
+
45
+ # Local Variables:
46
+ # mode: Ruby
47
+ # indent-tabs-mode: nil
48
+ # End:
@@ -0,0 +1,71 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for dient(1)
4
+ CVS_ID = '$Id: jlog_bench.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ $: << File.join(File.dirname($0), '..', '..', 'lib')
7
+
8
+ require 'benchmark'
9
+ require 'fileutils'
10
+ require 'higgs/jlog'
11
+
12
+ count = (ARGV.shift || '10000').to_i
13
+ log_size = (ARGV.shift || '16384').to_i
14
+ data_file = ARGV.shift || 'jlog_test.dat'
15
+
16
+ puts "#{$0}: COUNT:#{count}, LOG:#{log_size}"
17
+
18
+ class JLogWriteTask
19
+ def initialize(path, count, log_size, fsync, cksum_type)
20
+ @path = path
21
+ @count = count
22
+ @log_dat = 0xFF.chr * log_size
23
+ @fsync = fsync
24
+ @cksum_type = cksum_type
25
+ end
26
+
27
+ def open
28
+ log = Higgs::JournalLogger.open(@path, @fsync, @cksum_type)
29
+ begin
30
+ yield(log)
31
+ ensure
32
+ log.close
33
+ end
34
+ end
35
+ private :open
36
+
37
+ def call
38
+ open{|log|
39
+ @count.times do
40
+ log.write(@log_dat)
41
+ end
42
+ }
43
+ end
44
+ end
45
+
46
+ task_list = []
47
+ cksum_list = [ :SUM16, :MD5, :RMD160, :SHA1, :SHA256, :SHA384, :SHA512 ]
48
+ for cksum_type in cksum_list
49
+ task_list << [
50
+ "jlog write [#{cksum_type}]:",
51
+ JLogWriteTask.new(data_file, count, log_size, false, cksum_type)
52
+ ]
53
+ end
54
+ for cksum_type in cksum_list
55
+ task_list << [
56
+ "jlog write (fsync) [#{cksum_type}]:",
57
+ JLogWriteTask.new(data_file, count, log_size, true, cksum_type)
58
+ ]
59
+ end
60
+
61
+ Benchmark.bm(task_list.map{|n, t| n.length }.max) do |x|
62
+ FileUtils.rm_f(data_file)
63
+ task_list.each do |name, task|
64
+ x.report(name) { task.call }
65
+ end
66
+ end
67
+
68
+ # Local Variables:
69
+ # mode: Ruby
70
+ # indent-tabs-mode: nil
71
+ # End:
@@ -0,0 +1,128 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # for dient(1)
4
+ CVS_ID = '$Id: write_bench.rb 559 2007-09-25 15:20:20Z toki $'
5
+
6
+ require 'benchmark'
7
+
8
+ segment_count = (ARGV.shift || '10000').to_i
9
+ segment_size = (ARGV.shift || '16384').to_i
10
+ chunk_count = (ARGV.shift || '10').to_i
11
+ data_file = ARGV.shift || 'io_test.dat'
12
+
13
+ puts "#{$0}: COUNT:#{segment_count}, SEGMENT:#{segment_size}, CHUNK:#{chunk_count}"
14
+
15
+ class WriteTask
16
+ def initialize(path, count, size, chunk, fsync)
17
+ @path = path
18
+ @count = count
19
+ @chunk = chunk
20
+ @data = 0xFF.chr * size
21
+ @fsync = fsync
22
+ srand(0) # reset for rand
23
+ end
24
+
25
+ def open
26
+ begin
27
+ w = File.open(@path, File::WRONLY | File::CREAT | File::EXCL)
28
+ rescue Errno::EEXIST
29
+ w = File.open(@path, File::WRONLY)
30
+ end
31
+
32
+ begin
33
+ w.binmode
34
+ yield(w)
35
+ ensure
36
+ w.close
37
+ end
38
+ end
39
+ private :open
40
+
41
+ def io_sync(io)
42
+ if (@fsync) then
43
+ io.fsync
44
+ else
45
+ io.sync
46
+ end
47
+ end
48
+ private :io_sync
49
+ end
50
+
51
+ class SequentialWriteTask < WriteTask
52
+ def work
53
+ open{|w|
54
+ @count.times do |i|
55
+ w.write(@data)
56
+ if (i % @chunk == 0) then
57
+ io_sync(w)
58
+ end
59
+ end
60
+ io_sync(w)
61
+ }
62
+ end
63
+ end
64
+
65
+ class RandomWriteTask < WriteTask
66
+ def work
67
+ open{|w|
68
+ @count.times do |i|
69
+ pos = rand(@count)
70
+ w.seek(@data.size * pos)
71
+ w.write(@data)
72
+ if (i % @chunk == 0) then
73
+ io_sync(w)
74
+ end
75
+ end
76
+ io_sync(w)
77
+ }
78
+ end
79
+ end
80
+
81
+ class SortedRandomWriteTask < WriteTask
82
+ def work
83
+ open{|w|
84
+ write_list = []
85
+ @count.times do |i|
86
+ pos = rand(@count)
87
+ write_list << pos
88
+ if (i % @chunk == 0) then
89
+ write_list.sort!
90
+ for pos in write_list
91
+ w.seek(@data.size * pos)
92
+ w.write(@data)
93
+ end
94
+ write_list.clear
95
+ io_sync(w)
96
+ end
97
+ end
98
+
99
+ write_list.sort!
100
+ for pos in write_list
101
+ w.seek(@data.size * pos)
102
+ w.write(@data)
103
+ end
104
+ write_list.clear
105
+ io_sync(w)
106
+ }
107
+ end
108
+ end
109
+
110
+ task_list = [
111
+ [ 'seq write:', SequentialWriteTask.new(data_file, segment_count, segment_size, chunk_count, false) ],
112
+ [ 'seq write (fsync):', SequentialWriteTask.new(data_file, segment_count, segment_size, chunk_count, true) ],
113
+ [ 'rnd write:', RandomWriteTask.new(data_file, segment_count, segment_size, chunk_count, false) ],
114
+ [ 'rnd write (fsync):', RandomWriteTask.new(data_file, segment_count, segment_size, chunk_count, true) ],
115
+ [ 'sorted rnd write:', SortedRandomWriteTask.new(data_file, segment_count, segment_size, chunk_count, false) ],
116
+ [ 'sorted rnd write (fsync):', SortedRandomWriteTask.new(data_file, segment_count, segment_size, chunk_count, true) ]
117
+ ]
118
+
119
+ Benchmark.bm(task_list.map{|n,t| n.length }.max) do |x|
120
+ task_list.each do |name, work|
121
+ x.report(name) { work.work }
122
+ end
123
+ end
124
+
125
+ # Local Variables:
126
+ # mode: Ruby
127
+ # indent-tabs-mode: nil
128
+ # End: