extralite 2.5 → 2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +34 -13
  4. data/Gemfile +4 -0
  5. data/Gemfile-bundle +1 -1
  6. data/LICENSE +1 -1
  7. data/README.md +1059 -247
  8. data/Rakefile +18 -0
  9. data/TODO.md +0 -7
  10. data/examples/kv_store.rb +49 -0
  11. data/examples/multi_fiber.rb +16 -0
  12. data/examples/on_progress.rb +9 -0
  13. data/examples/pubsub_store_polyphony.rb +194 -0
  14. data/examples/pubsub_store_threads.rb +204 -0
  15. data/ext/extralite/changeset.c +463 -0
  16. data/ext/extralite/common.c +177 -91
  17. data/ext/extralite/database.c +745 -276
  18. data/ext/extralite/extconf-bundle.rb +10 -4
  19. data/ext/extralite/extconf.rb +34 -34
  20. data/ext/extralite/extralite.h +104 -47
  21. data/ext/extralite/extralite_ext.c +6 -0
  22. data/ext/extralite/iterator.c +14 -86
  23. data/ext/extralite/query.c +171 -264
  24. data/extralite-bundle.gemspec +1 -1
  25. data/extralite.gemspec +1 -1
  26. data/gemspec.rb +10 -11
  27. data/lib/extralite/version.rb +1 -1
  28. data/lib/extralite.rb +69 -10
  29. data/lib/sequel/adapters/extralite.rb +1 -1
  30. data/test/helper.rb +9 -1
  31. data/test/perf_argv_transform.rb +74 -0
  32. data/test/perf_ary.rb +14 -12
  33. data/test/perf_hash.rb +17 -15
  34. data/test/perf_hash_prepared.rb +58 -0
  35. data/test/perf_hash_transform.rb +66 -0
  36. data/test/perf_polyphony.rb +74 -0
  37. data/test/test_changeset.rb +161 -0
  38. data/test/test_database.rb +720 -104
  39. data/test/test_extralite.rb +2 -2
  40. data/test/test_iterator.rb +28 -13
  41. data/test/test_query.rb +352 -110
  42. data/test/test_sequel.rb +4 -4
  43. metadata +24 -16
  44. data/Gemfile.lock +0 -37
  45. data/test/perf_prepared.rb +0 -64
data/gemspec.rb CHANGED
@@ -8,19 +8,18 @@ def common_spec(s)
8
8
  s.files = `git ls-files`.split
9
9
  s.homepage = 'https://github.com/digital-fabric/extralite'
10
10
  s.metadata = {
11
- "source_code_uri" => "https://github.com/digital-fabric/extralite",
12
- "documentation_uri" => "https://www.rubydoc.info/gems/extralite",
13
- "homepage_uri" => "https://github.com/digital-fabric/extralite",
14
- "changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
11
+ 'homepage_uri' => 'https://github.com/digital-fabric/extralite',
12
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/extralite',
13
+ 'changelog_uri' => 'https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md'
15
14
  }
16
- s.rdoc_options = ["--title", "extralite", "--main", "README.md"]
17
- s.extra_rdoc_files = ["README.md"]
18
- s.require_paths = ["lib"]
15
+ s.rdoc_options = ['--title', 'Extralite', '--main', 'README.md']
16
+ s.extra_rdoc_files = ['README.md']
17
+ s.require_paths = ['lib']
19
18
  s.required_ruby_version = '>= 3.0'
20
19
 
21
- s.add_development_dependency 'rake-compiler', '1.1.6'
22
- s.add_development_dependency 'minitest', '5.15.0'
20
+ s.add_development_dependency 'rake-compiler', '1.2.7'
21
+ s.add_development_dependency 'minitest', '5.21.2'
23
22
  s.add_development_dependency 'simplecov', '0.17.1'
24
- s.add_development_dependency 'yard', '0.9.27'
25
- s.add_development_dependency 'sequel', '5.51.0'
23
+ s.add_development_dependency 'yard', '0.9.34'
24
+ s.add_development_dependency 'sequel', '5.77.0'
26
25
  end
@@ -1,4 +1,4 @@
1
1
  module Extralite
2
2
  # Extralite version
3
- VERSION = '2.5'
3
+ VERSION = '2.7'
4
4
  end
data/lib/extralite.rb CHANGED
@@ -29,10 +29,10 @@ module Extralite
29
29
  class ParameterError < Error
30
30
  end
31
31
 
32
- # An SQLite database
32
+ # This class encapsulates an SQLite database connection.
33
33
  class Database
34
34
  # @!visibility private
35
- TABLES_SQL = <<~SQL
35
+ TABLES_SQL = (<<~SQL).freeze
36
36
  SELECT name FROM %<db>s.sqlite_master
37
37
  WHERE type ='table'
38
38
  AND name NOT LIKE 'sqlite_%%';
@@ -46,10 +46,11 @@ module Extralite
46
46
  # @param db [String] name of attached database
47
47
  # @return [Array] list of tables
48
48
  def tables(db = 'main')
49
- query_single_column(format(TABLES_SQL, db: db))
49
+ query_argv(format(TABLES_SQL, db: db))
50
50
  end
51
51
 
52
- # Gets or sets one or more pragmas:
52
+ # Gets or sets one or more database pragmas. For a list of available pragmas
53
+ # see: https://sqlite.org/pragma.html#toc
53
54
  #
54
55
  # db.pragma(:cache_size) # get
55
56
  # db.pragma(cache_size: -2000) # set
@@ -60,6 +61,11 @@ module Extralite
60
61
  value.is_a?(Hash) ? pragma_set(value) : pragma_get(value)
61
62
  end
62
63
 
64
+ # Error class used to roll back a transaction without propagating an
65
+ # exception.
66
+ class Rollback < Error
67
+ end
68
+
63
69
  # Starts a transaction and runs the given block. If an exception is raised
64
70
  # in the block, the transaction is rolled back. Otherwise, the transaction
65
71
  # is commited after running the block.
@@ -69,20 +75,73 @@ module Extralite
69
75
  # raise if db.query_single_value('select x from bar') > 42
70
76
  # end
71
77
  #
72
- # @param mode [Symbol, String] transaction mode (deferred, immediate or exclusive). Defaults to immediate.
78
+ # For more information on transactions see:
79
+ # https://sqlite.org/lang_transaction.html
80
+ #
81
+ # @param mode [Symbol, String] transaction mode (deferred, immediate or exclusive).
73
82
  # @return [Any] the given block's return value
74
83
  def transaction(mode = :immediate)
75
- execute "begin #{mode} transaction"
76
-
77
84
  abort = false
85
+ execute "begin #{mode} transaction"
78
86
  yield self
79
- rescue
87
+ rescue => e
80
88
  abort = true
81
- raise
89
+ e.is_a?(Rollback) ? nil : raise
82
90
  ensure
83
91
  execute(abort ? 'rollback' : 'commit')
84
92
  end
85
93
 
94
+ # Creates a savepoint with the given name. For more information on
95
+ # savepoints see: https://sqlite.org/lang_savepoint.html
96
+ #
97
+ # db.savepoint(:savepoint1)
98
+ # db.execute('insert into foo values (42)')
99
+ # db.rollback_to(:savepoint1)
100
+ # db.release(:savepoint1)
101
+ #
102
+ # @param name [String, Symbol] savepoint name
103
+ # @return [Extralite::Database] database
104
+ def savepoint(name)
105
+ execute "savepoint #{name}"
106
+ self
107
+ end
108
+
109
+ # Release a savepoint with the given name. For more information on
110
+ # savepoints see: https://sqlite.org/lang_savepoint.html
111
+ #
112
+ # @param name [String, Symbol] savepoint name
113
+ # @return [Extralite::Database] database
114
+ def release(name)
115
+ execute "release #{name}"
116
+ self
117
+ end
118
+
119
+ # Rolls back changes to a savepoint with the given name. For more
120
+ # information on savepoints see: https://sqlite.org/lang_savepoint.html
121
+ #
122
+ # @param name [String, Symbol] savepoint name
123
+ # @return [Extralite::Database] database
124
+ def rollback_to(name)
125
+ execute "rollback to #{name}"
126
+ self
127
+ end
128
+
129
+ # Rolls back the currently active transaction. This method should only be
130
+ # called from within a block passed to `Database#transaction`. This method
131
+ # raises a Extralite::Rollback exception, which will stop execution of the
132
+ # transaction block without propagating the exception.
133
+ #
134
+ # db.transaction do
135
+ # db.execute('insert into foo (42)')
136
+ # db.rollback!
137
+ # end
138
+ #
139
+ # @param name [String, Symbol] savepoint name
140
+ # @return [Extralite::Database] database
141
+ def rollback!
142
+ raise Rollback
143
+ end
144
+
86
145
  private
87
146
 
88
147
  def pragma_set(values)
@@ -91,7 +150,7 @@ module Extralite
91
150
  end
92
151
 
93
152
  def pragma_get(key)
94
- query_single_value("pragma #{key}")
153
+ query_single_argv("pragma #{key}")
95
154
  end
96
155
  end
97
156
 
@@ -362,7 +362,7 @@ module Sequel
362
362
  def fetch_rows(sql, &block)
363
363
  execute(sql) do |result, columns|
364
364
  self.columns = columns
365
- max = columns.size
365
+ # max = columns.size
366
366
  result.each(&block)
367
367
  end
368
368
  end
data/test/helper.rb CHANGED
@@ -7,4 +7,12 @@ require 'minitest/autorun'
7
7
  puts "sqlite3 version: #{Extralite.sqlite3_version}"
8
8
 
9
9
  IS_LINUX = RUBY_PLATFORM =~ /linux/
10
- SKIP_RACTOR_TESTS = !IS_LINUX || (RUBY_VERSION =~ /^3\.0/)
10
+ # Ractors are kinda flaky, there's no point in testing this
11
+ SKIP_RACTOR_TESTS = true #!IS_LINUX || (RUBY_VERSION =~ /^3\.[01]/)
12
+
13
+ module Minitest::Assertions
14
+ def assert_in_range exp_range, act
15
+ msg = message(msg) { "Expected #{mu_pp(act)} to be in range #{mu_pp(exp_range)}" }
16
+ assert exp_range.include?(act), msg
17
+ end
18
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run on Ruby 3.3 with YJIT enabled
4
+
5
+ require 'bundler/inline'
6
+
7
+ gemfile do
8
+ source 'https://rubygems.org'
9
+ gem 'extralite', path: '..'
10
+ gem 'benchmark-ips'
11
+ end
12
+
13
+ require 'benchmark/ips'
14
+ require 'fileutils'
15
+
16
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
17
+ puts "DB_PATH = #{DB_PATH.inspect}"
18
+
19
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
20
+
21
+ def prepare_database(count)
22
+ $extralite_db.query('create table if not exists foo (b text)')
23
+ $extralite_db.query('delete from foo')
24
+ $extralite_db.query('begin')
25
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
26
+ $extralite_db.query('commit')
27
+ end
28
+
29
+ class Model
30
+ def initialize(h)
31
+ @h = h
32
+ end
33
+
34
+ def values
35
+ @h
36
+ end
37
+ end
38
+
39
+ TRANSFORM = ->(b) { { b: b } }
40
+
41
+ def extralite_run_ary_map(count)
42
+ results = []
43
+ $extralite_db.query_ary('select * from foo') { |(b)| results << { b: b } }
44
+ raise unless results.size == count
45
+ end
46
+
47
+ def extralite_run_argv_map(count)
48
+ results = []
49
+ $extralite_db.query_argv('select * from foo') { |b| results << { b: b } }
50
+ raise unless results.size == count
51
+ end
52
+
53
+ def extralite_run_transform(count)
54
+ results = $extralite_db.query_argv(TRANSFORM, 'select * from foo')
55
+ raise unless results.size == count
56
+ end
57
+
58
+ [10, 1000, 100000].each do |c|
59
+ puts "Record count: #{c}"
60
+ prepare_database(c)
61
+
62
+ bm = Benchmark.ips do |x|
63
+ x.config(:time => 5, :warmup => 2)
64
+
65
+ x.report("ary_map") { extralite_run_ary_map(c) }
66
+ x.report("argv_map") { extralite_run_argv_map(c) }
67
+ x.report("transform") { extralite_run_transform(c) }
68
+
69
+ x.compare!
70
+ end
71
+ puts;
72
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
73
+ puts;
74
+ end
data/test/perf_ary.rb CHANGED
@@ -15,26 +15,25 @@ require 'fileutils'
15
15
  DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
16
  puts "DB_PATH = #{DB_PATH.inspect}"
17
17
 
18
+ $sqlite3_db = SQLite3::Database.new(DB_PATH)
19
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
18
20
 
19
21
  def prepare_database(count)
20
22
  db = Extralite::Database.new(DB_PATH)
21
- db.query('create table if not exists foo ( a integer primary key, b text )')
22
- db.query('delete from foo')
23
- db.query('begin')
24
- count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
25
- db.query('commit')
26
- db.close
23
+ $extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
24
+ $extralite_db.query('delete from foo')
25
+ $extralite_db.query('begin')
26
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
27
+ $extralite_db.query('commit')
27
28
  end
28
29
 
29
30
  def sqlite3_run(count)
30
- db = SQLite3::Database.new(DB_PATH)
31
- results = db.execute('select * from foo')
31
+ results = $sqlite3_db.execute('select * from foo')
32
32
  raise unless results.size == count
33
33
  end
34
34
 
35
35
  def extralite_run(count)
36
- db = Extralite::Database.new(DB_PATH)
37
- results = db.query_ary('select * from foo')
36
+ results = $extralite_db.query('select * from foo')
38
37
  raise unless results.size == count
39
38
  end
40
39
 
@@ -43,12 +42,15 @@ end
43
42
 
44
43
  prepare_database(c)
45
44
 
46
- Benchmark.ips do |x|
47
- x.config(:time => 3, :warmup => 1)
45
+ bm = Benchmark.ips do |x|
46
+ x.config(:time => 5, :warmup => 2)
48
47
 
49
48
  x.report("sqlite3") { sqlite3_run(c) }
50
49
  x.report("extralite") { extralite_run(c) }
51
50
 
52
51
  x.compare!
53
52
  end
53
+ puts;
54
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
55
+ puts;
54
56
  end
data/test/perf_hash.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Run on Ruby 3.3 with YJIT enabled
4
+
3
5
  require 'bundler/inline'
4
6
 
5
7
  gemfile do
@@ -15,40 +17,40 @@ require 'fileutils'
15
17
  DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
18
  puts "DB_PATH = #{DB_PATH.inspect}"
17
19
 
20
+ $sqlite3_db = SQLite3::Database.new(DB_PATH, results_as_hash: true)
21
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
22
+
18
23
  def prepare_database(count)
19
- db = Extralite::Database.new(DB_PATH)
20
- db.query('create table if not exists foo ( a integer primary key, b text )')
21
- db.query('delete from foo')
22
- db.query('begin')
23
- count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
24
- db.query('commit')
25
- db.close
24
+ $extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
25
+ $extralite_db.query('delete from foo')
26
+ $extralite_db.query('begin')
27
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
28
+ $extralite_db.query('commit')
26
29
  end
27
30
 
28
31
  def sqlite3_run(count)
29
- db = SQLite3::Database.new(DB_PATH, :results_as_hash => true)
30
- results = db.execute('select * from foo')
32
+ results = $sqlite3_db.execute('select * from foo')
31
33
  raise unless results.size == count
32
34
  end
33
35
 
34
36
  def extralite_run(count)
35
- db = Extralite::Database.new(DB_PATH)
36
- results = db.query('select * from foo')
37
+ results = $extralite_db.query('select * from foo')
37
38
  raise unless results.size == count
38
39
  end
39
40
 
40
41
  [10, 1000, 100000].each do |c|
41
42
  puts "Record count: #{c}"
42
-
43
43
  prepare_database(c)
44
44
 
45
- Benchmark.ips do |x|
46
- x.config(:time => 3, :warmup => 1)
45
+ bm = Benchmark.ips do |x|
46
+ x.config(:time => 5, :warmup => 2)
47
47
 
48
48
  x.report("sqlite3") { sqlite3_run(c) }
49
49
  x.report("extralite") { extralite_run(c) }
50
50
 
51
51
  x.compare!
52
52
  end
53
- puts; puts;
53
+ puts;
54
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
55
+ puts;
54
56
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'extralite', path: '..'
8
+ gem 'sqlite3'
9
+ gem 'benchmark-ips'
10
+ end
11
+
12
+ require 'benchmark/ips'
13
+ require 'fileutils'
14
+
15
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
+ puts "DB_PATH = #{DB_PATH.inspect}"
17
+
18
+ def prepare_database(count)
19
+ $sqlite3_db = SQLite3::Database.new(DB_PATH, results_as_hash: true)
20
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
21
+
22
+ $extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
23
+ $extralite_db.query('delete from foo')
24
+ $extralite_db.query('begin')
25
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
26
+ $extralite_db.query('commit')
27
+
28
+ $sqlite3_stmt = $sqlite3_db.prepare('select * from foo')
29
+ $extralite_q = $extralite_db.prepare('select * from foo')
30
+ end
31
+
32
+ def sqlite3_run(count)
33
+ results = $sqlite3_stmt.execute
34
+ raise unless results.to_a.size == count
35
+ end
36
+
37
+ def extralite_run(count)
38
+ results = $extralite_q.to_a
39
+ raise unless results.size == count
40
+ end
41
+
42
+ [10, 1000, 100000].each do |c|
43
+ puts "Record count: #{c}"
44
+
45
+ prepare_database(c)
46
+
47
+ bm = Benchmark.ips do |x|
48
+ x.config(:time => 5, :warmup => 2)
49
+
50
+ x.report("sqlite3") { sqlite3_run(c) }
51
+ x.report("extralite") { extralite_run(c) }
52
+
53
+ x.compare!
54
+ end
55
+ puts;
56
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
57
+ puts;
58
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run on Ruby 3.3 with YJIT enabled
4
+
5
+ require 'bundler/inline'
6
+
7
+ gemfile do
8
+ source 'https://rubygems.org'
9
+ gem 'extralite', path: '..'
10
+ gem 'benchmark-ips'
11
+ end
12
+
13
+ require 'benchmark/ips'
14
+ require 'fileutils'
15
+
16
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
17
+ puts "DB_PATH = #{DB_PATH.inspect}"
18
+
19
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
20
+
21
+ def prepare_database(count)
22
+ $extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
23
+ $extralite_db.query('delete from foo')
24
+ $extralite_db.query('begin')
25
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
26
+ $extralite_db.query('commit')
27
+ end
28
+
29
+ class Model
30
+ def initialize(h)
31
+ @h = h
32
+ end
33
+
34
+ def values
35
+ @h
36
+ end
37
+ end
38
+
39
+ TRANSFORM = ->(h) { Model.new(h) }
40
+
41
+ def extralite_run_map(count)
42
+ results = $extralite_db.query('select * from foo').map(&TRANSFORM)
43
+ raise unless results.size == count
44
+ end
45
+
46
+ def extralite_run_transform(count)
47
+ results = $extralite_db.query(TRANSFORM, 'select * from foo')
48
+ raise unless results.size == count
49
+ end
50
+
51
+ [10, 1000, 100000].each do |c|
52
+ puts "Record count: #{c}"
53
+ prepare_database(c)
54
+
55
+ bm = Benchmark.ips do |x|
56
+ x.config(:time => 5, :warmup => 2)
57
+
58
+ x.report("map") { extralite_run_map(c) }
59
+ x.report("transform") { extralite_run_transform(c) }
60
+
61
+ x.compare!
62
+ end
63
+ puts;
64
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
65
+ puts;
66
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run on Ruby 3.3 with YJIT enabled
4
+
5
+ require 'bundler/inline'
6
+ gemfile do
7
+ gem 'polyphony'
8
+ gem 'extralite', path: '.'
9
+ gem 'benchmark-ips'
10
+ end
11
+
12
+ require 'benchmark/ips'
13
+ require 'polyphony'
14
+
15
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
+ puts "DB_PATH = #{DB_PATH.inspect}"
17
+
18
+ $db1 = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
19
+ $db2 = Extralite::Database.new(DB_PATH, gvl_release_threshold: 0)
20
+ $db3 = Extralite::Database.new(DB_PATH)
21
+
22
+ $snooze_count = 0
23
+ $db3.on_progress(25) { $snooze_count += 1; snooze }
24
+
25
+ def prepare_database(count)
26
+ $db1.execute('create table if not exists foo ( a integer primary key, b text )')
27
+ $db1.transaction do
28
+ $db1.execute('delete from foo')
29
+ rows = count.times.map { "hello#{rand(1000)}" }
30
+ $db1.batch_execute('insert into foo (b) values (?)', rows)
31
+ end
32
+ end
33
+
34
+ def extralite_run1(count)
35
+ results = $db1.query('select * from foo')
36
+ raise unless results.size == count
37
+ end
38
+
39
+ def extralite_run2(count)
40
+ results = $db2.query('select * from foo')
41
+ raise unless results.size == count
42
+ end
43
+
44
+ def extralite_run3(count)
45
+ results = $db3.query('select * from foo')
46
+ raise unless results.size == count
47
+ end
48
+
49
+ [10, 1000, 100000].each do |c|
50
+ puts "Record count: #{c}"
51
+ prepare_database(c)
52
+
53
+ bm = Benchmark.ips do |x|
54
+ x.config(:time => 3, :warmup => 1)
55
+
56
+ x.report('GVL threshold -1') { extralite_run1(c) }
57
+ x.report('GVL threshold 0') { extralite_run2(c) }
58
+ $snooze_count = 0
59
+ x.report('on_progress 1000') { extralite_run3(c) }
60
+
61
+ x.compare!
62
+ end
63
+ puts;
64
+ bm.entries.each do |e|
65
+ score = (e.ips * c).round.to_i
66
+ if e.label == 'on_progress 1000'
67
+ snooze_rate = ($snooze_count / e.seconds).to_i
68
+ puts "#{e.label}: #{score} rows/s snoozes: #{snooze_rate} i/s"
69
+ else
70
+ puts "#{e.label}: #{score} rows/s"
71
+ end
72
+ end
73
+ puts;
74
+ end