oj 3.11.5 → 3.16.5

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 (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +19 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +20 -6
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +10 -9
  9. data/ext/oj/circarray.c +8 -6
  10. data/ext/oj/circarray.h +2 -2
  11. data/ext/oj/code.c +19 -33
  12. data/ext/oj/code.h +2 -2
  13. data/ext/oj/compat.c +27 -77
  14. data/ext/oj/custom.c +86 -179
  15. data/ext/oj/debug.c +126 -0
  16. data/ext/oj/dump.c +256 -249
  17. data/ext/oj/dump.h +26 -12
  18. data/ext/oj/dump_compat.c +565 -642
  19. data/ext/oj/dump_leaf.c +17 -63
  20. data/ext/oj/dump_object.c +65 -187
  21. data/ext/oj/dump_strict.c +27 -51
  22. data/ext/oj/encoder.c +43 -0
  23. data/ext/oj/err.c +2 -13
  24. data/ext/oj/err.h +24 -8
  25. data/ext/oj/extconf.rb +21 -6
  26. data/ext/oj/fast.c +149 -149
  27. data/ext/oj/intern.c +313 -0
  28. data/ext/oj/intern.h +22 -0
  29. data/ext/oj/mem.c +318 -0
  30. data/ext/oj/mem.h +53 -0
  31. data/ext/oj/mimic_json.c +121 -106
  32. data/ext/oj/object.c +85 -162
  33. data/ext/oj/odd.c +89 -67
  34. data/ext/oj/odd.h +15 -15
  35. data/ext/oj/oj.c +542 -411
  36. data/ext/oj/oj.h +99 -73
  37. data/ext/oj/parse.c +175 -187
  38. data/ext/oj/parse.h +26 -24
  39. data/ext/oj/parser.c +1600 -0
  40. data/ext/oj/parser.h +101 -0
  41. data/ext/oj/rails.c +112 -159
  42. data/ext/oj/rails.h +1 -1
  43. data/ext/oj/reader.c +11 -14
  44. data/ext/oj/reader.h +4 -2
  45. data/ext/oj/resolve.c +5 -24
  46. data/ext/oj/rxclass.c +7 -6
  47. data/ext/oj/rxclass.h +1 -1
  48. data/ext/oj/saj.c +22 -33
  49. data/ext/oj/saj2.c +584 -0
  50. data/ext/oj/saj2.h +23 -0
  51. data/ext/oj/scp.c +5 -28
  52. data/ext/oj/sparse.c +28 -72
  53. data/ext/oj/stream_writer.c +50 -40
  54. data/ext/oj/strict.c +56 -61
  55. data/ext/oj/string_writer.c +72 -39
  56. data/ext/oj/trace.h +31 -4
  57. data/ext/oj/usual.c +1218 -0
  58. data/ext/oj/usual.h +69 -0
  59. data/ext/oj/util.h +1 -1
  60. data/ext/oj/val_stack.c +14 -3
  61. data/ext/oj/val_stack.h +8 -7
  62. data/ext/oj/validate.c +46 -0
  63. data/ext/oj/wab.c +63 -88
  64. data/lib/oj/active_support_helper.rb +1 -3
  65. data/lib/oj/bag.rb +7 -1
  66. data/lib/oj/easy_hash.rb +4 -5
  67. data/lib/oj/error.rb +1 -2
  68. data/lib/oj/json.rb +162 -150
  69. data/lib/oj/mimic.rb +9 -7
  70. data/lib/oj/saj.rb +20 -6
  71. data/lib/oj/schandler.rb +5 -4
  72. data/lib/oj/state.rb +12 -8
  73. data/lib/oj/version.rb +1 -2
  74. data/lib/oj.rb +2 -0
  75. data/pages/Compatibility.md +1 -1
  76. data/pages/InstallOptions.md +20 -0
  77. data/pages/JsonGem.md +15 -0
  78. data/pages/Modes.md +8 -3
  79. data/pages/Options.md +43 -5
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +14 -2
  82. data/test/_test_active.rb +8 -9
  83. data/test/_test_active_mimic.rb +7 -8
  84. data/test/_test_mimic_rails.rb +17 -20
  85. data/test/activerecord/result_test.rb +5 -6
  86. data/test/activesupport6/encoding_test.rb +63 -28
  87. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  88. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  89. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  90. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  91. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  92. data/test/files.rb +15 -15
  93. data/test/foo.rb +16 -45
  94. data/test/helper.rb +11 -8
  95. data/test/isolated/shared.rb +3 -2
  96. data/test/json_gem/json_addition_test.rb +2 -2
  97. data/test/json_gem/json_common_interface_test.rb +8 -6
  98. data/test/json_gem/json_encoding_test.rb +0 -0
  99. data/test/json_gem/json_ext_parser_test.rb +1 -0
  100. data/test/json_gem/json_fixtures_test.rb +3 -2
  101. data/test/json_gem/json_generator_test.rb +56 -38
  102. data/test/json_gem/json_generic_object_test.rb +11 -11
  103. data/test/json_gem/json_parser_test.rb +54 -47
  104. data/test/json_gem/json_string_matching_test.rb +9 -9
  105. data/test/json_gem/test_helper.rb +7 -3
  106. data/test/mem.rb +34 -0
  107. data/test/perf.rb +22 -27
  108. data/test/perf_compat.rb +31 -33
  109. data/test/perf_dump.rb +50 -0
  110. data/test/perf_fast.rb +80 -82
  111. data/test/perf_file.rb +27 -29
  112. data/test/perf_object.rb +65 -69
  113. data/test/perf_once.rb +59 -0
  114. data/test/perf_parser.rb +183 -0
  115. data/test/perf_saj.rb +46 -54
  116. data/test/perf_scp.rb +58 -69
  117. data/test/perf_simple.rb +41 -39
  118. data/test/perf_strict.rb +74 -82
  119. data/test/perf_wab.rb +67 -69
  120. data/test/prec.rb +5 -5
  121. data/test/sample/change.rb +0 -1
  122. data/test/sample/dir.rb +0 -1
  123. data/test/sample/doc.rb +0 -1
  124. data/test/sample/file.rb +0 -1
  125. data/test/sample/group.rb +0 -1
  126. data/test/sample/hasprops.rb +0 -1
  127. data/test/sample/layer.rb +0 -1
  128. data/test/sample/rect.rb +0 -1
  129. data/test/sample/shape.rb +0 -1
  130. data/test/sample/text.rb +0 -1
  131. data/test/sample.rb +16 -16
  132. data/test/sample_json.rb +8 -8
  133. data/test/test_compat.rb +95 -43
  134. data/test/test_custom.rb +73 -51
  135. data/test/test_debian.rb +7 -10
  136. data/test/test_fast.rb +135 -79
  137. data/test/test_file.rb +41 -30
  138. data/test/test_gc.rb +16 -5
  139. data/test/test_generate.rb +5 -5
  140. data/test/test_hash.rb +5 -5
  141. data/test/test_integer_range.rb +9 -9
  142. data/test/test_null.rb +20 -20
  143. data/test/test_object.rb +99 -96
  144. data/test/test_parser.rb +11 -0
  145. data/test/test_parser_debug.rb +27 -0
  146. data/test/test_parser_saj.rb +337 -0
  147. data/test/test_parser_usual.rb +251 -0
  148. data/test/test_rails.rb +2 -2
  149. data/test/test_saj.rb +10 -8
  150. data/test/test_scp.rb +37 -39
  151. data/test/test_strict.rb +40 -32
  152. data/test/test_various.rb +165 -84
  153. data/test/test_wab.rb +48 -44
  154. data/test/test_writer.rb +47 -47
  155. data/test/tests.rb +13 -5
  156. data/test/tests_mimic.rb +12 -3
  157. data/test/tests_mimic_addition.rb +12 -3
  158. metadata +74 -128
  159. data/ext/oj/hash.c +0 -131
  160. data/ext/oj/hash.h +0 -19
  161. data/ext/oj/hash_test.c +0 -491
  162. data/test/activesupport4/decoding_test.rb +0 -108
  163. data/test/activesupport4/encoding_test.rb +0 -531
  164. data/test/activesupport4/test_helper.rb +0 -41
  165. data/test/activesupport5/test_helper.rb +0 -72
  166. data/test/bar.rb +0 -35
  167. data/test/baz.rb +0 -16
  168. data/test/zoo.rb +0 -13
data/test/perf_object.rb CHANGED
@@ -1,14 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $: << '.'
4
- $: << '../lib'
5
- $: << '../ext'
4
+ $LOAD_PATH << '.'
5
+ $LOAD_PATH << '../lib'
6
+ $LOAD_PATH << '../ext'
6
7
 
7
- if __FILE__ == $0
8
- if (i = ARGV.index('-I'))
9
- x,path = ARGV.slice!(i, 2)
10
- $: << path
11
- end
8
+ if __FILE__ == $PROGRAM_NAME && (i = ARGV.index('-I'))
9
+ _, path = ARGV.slice!(i, 2)
10
+ $LOAD_PATH << path
12
11
  end
13
12
 
14
13
  require 'optparse'
@@ -18,9 +17,9 @@ require 'perf'
18
17
  require 'sample'
19
18
  require 'files'
20
19
 
21
- $circular = false
22
- $indent = 0
23
- $allow_gc = true
20
+ @circular = false
21
+ @indent = 0
22
+ @allow_gc = true
24
23
 
25
24
  do_sample = false
26
25
  do_files = false
@@ -29,34 +28,34 @@ do_load = false
29
28
  do_dump = false
30
29
  do_read = false
31
30
  do_write = false
32
- $iter = 1000
33
- $mult = 1
31
+ @iter = 1000
32
+ @mult = 1
34
33
 
35
34
  opts = OptionParser.new
36
- opts.on("-c", "circular options") { $circular = true }
35
+ opts.on('-c', 'circular options') { @circular = true }
37
36
 
38
- opts.on("-x", "use sample instead of files") { do_sample = true }
39
- opts.on("-g", "no GC during parsing") { $allow_gc = false }
37
+ opts.on('-x', 'use sample instead of files') { do_sample = true }
38
+ opts.on('-g', 'no GC during parsing') { @allow_gc = false }
40
39
 
41
- opts.on("-s", "load and dump as sample Ruby object") { do_sample = true }
42
- opts.on("-f", "load and dump as files Ruby object") { do_files = true }
40
+ opts.on('-s', 'load and dump as sample Ruby object') { do_sample = true }
41
+ opts.on('-f', 'load and dump as files Ruby object') { do_files = true }
43
42
 
44
- opts.on("-l", "load") { do_load = true }
45
- opts.on("-d", "dump") { do_dump = true }
46
- opts.on("-r", "read") { do_read = true }
47
- opts.on("-w", "write") { do_write = true }
48
- opts.on("-a", "load, dump, read and write") { do_load = true; do_dump = true; do_read = true; do_write = true }
43
+ opts.on('-l', 'load') { do_load = true }
44
+ opts.on('-d', 'dump') { do_dump = true }
45
+ opts.on('-r', 'read') { do_read = true }
46
+ opts.on('-w', 'write') { do_write = true }
47
+ opts.on('-a', 'load, dump, read and write') { do_load = true; do_dump = true; do_read = true; do_write = true }
49
48
 
50
- opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i }
51
- opts.on("-m", "--multiply [Int]", Integer, "multiplier") { |i| $mult = i }
49
+ opts.on('-i', '--iterations [Int]', Integer, 'iterations') { |v| @iter = v }
50
+ opts.on('-m', '--multiply [Int]', Integer, 'multiplier') { |v| @mult = v }
52
51
 
53
- opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
52
+ opts.on('-h', '--help', 'Show this display') { puts opts; Process.exit!(0) }
54
53
  files = opts.parse(ARGV)
55
54
 
56
- $obj = nil
57
- $xml = nil
58
- $mars = nil
59
- $json = nil
55
+ @obj = nil
56
+ @xml = nil
57
+ @mars = nil
58
+ @json = nil
60
59
 
61
60
  unless do_load || do_dump || do_read || do_write
62
61
  do_load = true
@@ -67,72 +66,69 @@ end
67
66
 
68
67
  # prepare all the formats for input
69
68
  if files.empty?
70
- $obj = []
71
- $mult.times do
72
- $obj << (do_sample ? sample_doc(2) : files('..'))
69
+ @obj = []
70
+ @mult.times do
71
+ @obj << (do_sample ? sample_doc(2) : files('..'))
73
72
  end
74
73
 
75
- $mars = Marshal.dump($obj)
76
- $xml = Ox.dump($obj, :indent => $indent, :circular => $circular)
77
- $json = Oj.dump($obj, :indent => $indent, :circular => $circular, :mode => :object)
78
- File.open('sample.xml', 'w') { |f| f.write($xml) }
79
- File.open('sample.json', 'w') { |f| f.write($json) }
80
- File.open('sample.marshal', 'w') { |f| f.write($mars) }
74
+ @mars = Marshal.dump(@obj)
75
+ @xml = Ox.dump(@obj, :indent => @indent, :circular => @circular)
76
+ @json = Oj.dump(@obj, :indent => @indent, :circular => @circular, :mode => :object)
77
+ File.write('sample.xml', @xml)
78
+ File.write('sample.json', @json)
79
+ File.write('sample.marshal', @mars)
81
80
  else
82
81
  puts "loading and parsing #{files}\n\n"
83
- data = files.map do |f|
84
- $xml = File.read(f)
85
- $obj = Ox.load($xml);
86
- $mars = Marshal.dump($obj)
87
- $json = Oj.dump($obj, :indent => $indent, :circular => $circular)
82
+ files.map do |f|
83
+ @xml = File.read(f)
84
+ @obj = Ox.load(@xml)
85
+ @mars = Marshal.dump(@obj)
86
+ @json = Oj.dump(@obj, :indent => @indent, :circular => @circular)
88
87
  end
89
88
  end
90
89
 
91
- Oj.default_options = { :mode => :object, :indent => $indent, :circular => $circular, :allow_gc => $allow_gc }
92
- #puts "json: #{$json.size}"
93
- #puts "xml: #{$xml.size}"
94
- #puts "marshal: #{$mars.size}"
95
-
90
+ Oj.default_options = { :mode => :object, :indent => @indent, :circular => @circular, :allow_gc => @allow_gc }
91
+ # puts "json: #{@json.size}"
92
+ # puts "xml: #{@xml.size}"
93
+ # puts "marshal: #{@mars.size}"
96
94
 
97
95
  if do_load
98
96
  puts '-' * 80
99
- puts "Load Performance"
97
+ puts 'Load Performance'
100
98
  perf = Perf.new()
101
- perf.add('Oj.object', 'load') { Oj.object_load($json) }
102
- perf.add('Ox', 'load') { Ox.load($xml, :mode => :object) }
103
- perf.add('Marshal', 'load') { Marshal.load($mars) }
104
- perf.run($iter)
99
+ perf.add('Oj.object', 'load') { Oj.object_load(@json) }
100
+ perf.add('Ox', 'load') { Ox.load(@xml, :mode => :object) }
101
+ perf.add('Marshal', 'load') { Marshal.load(@mars) }
102
+ perf.run(@iter)
105
103
  end
106
104
 
107
105
  if do_dump
108
106
  puts '-' * 80
109
- puts "Dump Performance"
107
+ puts 'Dump Performance'
110
108
  perf = Perf.new()
111
- perf.add('Oj', 'dump') { Oj.dump($obj) }
112
- perf.add('Ox', 'dump') { Ox.dump($obj, :indent => $indent, :circular => $circular) }
113
- perf.add('Marshal', 'dump') { Marshal.dump($obj) }
114
- perf.run($iter)
109
+ perf.add('Oj', 'dump') { Oj.dump(@obj) }
110
+ perf.add('Ox', 'dump') { Ox.dump(@obj, :indent => @indent, :circular => @circular) }
111
+ perf.add('Marshal', 'dump') { Marshal.dump(@obj) }
112
+ perf.run(@iter)
115
113
  end
116
114
 
117
115
  if do_read
118
116
  puts '-' * 80
119
- puts "Read from file Performance"
117
+ puts 'Read from file Performance'
120
118
  perf = Perf.new()
121
119
  perf.add('Oj', 'load') { Oj.load_file('sample.json') }
122
- #perf.add('Oj', 'load') { Oj.load(File.read('sample.json')) }
120
+ # perf.add('Oj', 'load') { Oj.load(File.read('sample.json')) }
123
121
  perf.add('Ox', 'load_file') { Ox.load_file('sample.xml', :mode => :object) }
124
122
  perf.add('Marshal', 'load') { Marshal.load(File.new('sample.marshal')) }
125
- perf.run($iter)
123
+ perf.run(@iter)
126
124
  end
127
125
 
128
126
  if do_write
129
127
  puts '-' * 80
130
- puts "Write to file Performance"
128
+ puts 'Write to file Performance'
131
129
  perf = Perf.new()
132
- perf.add('Oj', 'to_file') { Oj.to_file('sample.json', $obj) }
133
- perf.add('Ox', 'to_file') { Ox.to_file('sample.xml', $obj, :indent => $indent, :circular => $circular) }
134
- perf.add('Marshal', 'dump') { Marshal.dump($obj, File.new('sample.marshal', 'w')) }
135
- perf.run($iter)
130
+ perf.add('Oj', 'to_file') { Oj.to_file('sample.json', @obj) }
131
+ perf.add('Ox', 'to_file') { Ox.to_file('sample.xml', @obj, :indent => @indent, :circular => @circular) }
132
+ perf.add('Marshal', 'dump') { Marshal.dump(@obj, File.new('sample.marshal', 'w')) }
133
+ perf.run(@iter)
136
134
  end
137
-
138
-
data/test/perf_once.rb ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'English'
5
+ $LOAD_PATH << '.'
6
+ $LOAD_PATH << File.join(__dir__, '../lib')
7
+ $LOAD_PATH << File.join(__dir__, '../ext')
8
+
9
+ require 'oj'
10
+
11
+ filename = 'tmp.json'
12
+ File.open(filename, 'w') { |f|
13
+ cnt = 0
14
+ f.puts('{')
15
+ ('a'..'z').each { |a|
16
+ ('a'..'z').each { |b|
17
+ ('a'..'z').each { |c|
18
+ ('a'..'z').each { |d|
19
+ f.puts(%|"#{a}#{b}#{c}#{d}":#{cnt},|)
20
+ cnt += 1
21
+ }
22
+ }
23
+ }
24
+ }
25
+ f.puts('"_last":0}')
26
+ }
27
+
28
+ def mem
29
+ `ps -o rss= -p #{$PROCESS_ID}`.to_i
30
+ end
31
+
32
+ Oj.default_options = { mode: :strict, cache_keys: false, cache_str: -1 }
33
+ start = Time.now
34
+ Oj.load_file('tmp.json')
35
+ dur = Time.now - start
36
+ GC.start
37
+ puts "no cache duration: #{dur} @ #{mem}"
38
+
39
+ Oj.default_options = { cache_keys: true }
40
+ start = Time.now
41
+ Oj.load_file('tmp.json')
42
+ dur = Time.now - start
43
+ GC.start
44
+ puts "initial cache duration: #{dur} @ #{mem}"
45
+
46
+ start = Time.now
47
+ Oj.load_file('tmp.json')
48
+ dur = Time.now - start
49
+ GC.start
50
+ puts "second cache duration: #{dur} @ #{mem}"
51
+
52
+ 10.times { GC.start }
53
+ start = Time.now
54
+ Oj.load_file('tmp.json')
55
+ dur = Time.now - start
56
+ GC.start
57
+ puts "after several GCs cache duration: #{dur} @ #{mem}"
58
+
59
+ # TBD check memory use
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH << '.'
5
+ $LOAD_PATH << File.join(__dir__, '../lib')
6
+ $LOAD_PATH << File.join(__dir__, '../ext')
7
+
8
+ require 'optparse'
9
+ require 'perf'
10
+ require 'oj'
11
+ require 'json'
12
+
13
+ $verbose = false
14
+ $iter = 50_000
15
+ $with_bignum = false
16
+ $size = 1
17
+ $cache_keys = true
18
+ $symbol_keys = false
19
+
20
+ opts = OptionParser.new
21
+ opts.on('-v', 'verbose') { $verbose = true }
22
+ opts.on('-c', '--count [Int]', Integer, 'iterations') { |i| $iter = i }
23
+ opts.on('-s', '--size [Int]', Integer, 'size (~Kbytes)') { |i| $size = i }
24
+ opts.on('-b', 'with bignum') { $with_bignum = true }
25
+ opts.on('-k', 'no cache') { $cache_keys = false }
26
+ opts.on('-sym', 'symbol keys') { $symbol_keys = true }
27
+ opts.on('-h', '--help', 'Show this display') { puts opts; Process.exit!(0) }
28
+ opts.parse(ARGV)
29
+
30
+ $obj = {
31
+ 'a' => 'Alpha', # string
32
+ 'b' => true, # boolean
33
+ 'c' => 12_345, # number
34
+ 'd' => [ true, [false, [-123_456_789, nil], 3.9676, ['Something else.', false, 1, nil], nil]], # mix it up array
35
+ 'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
36
+ 'f' => nil, # nil
37
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
38
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
39
+ }
40
+ $obj['g'] = 12_345_678_901_234_567_890_123_456_789 if $with_bignum
41
+
42
+ if 0 < $size
43
+ o = $obj
44
+ $obj = []
45
+ (4 * $size).times do
46
+ $obj << o
47
+ end
48
+ end
49
+
50
+ $json = Oj.dump($obj)
51
+ $failed = {} # key is same as String used in tests later
52
+ Oj.default_options = {create_id: '^', create_additions: true, class_cache: true}
53
+ Oj.default_options = if $cache_keys
54
+ {cache_keys: true, cache_str: 6, symbol_keys: $symbol_keys}
55
+ else
56
+ {cache_keys: false, cache_str: -1, symbol_keys: $symbol_keys}
57
+ end
58
+ JSON.parser = JSON::Ext::Parser
59
+
60
+ class AllSaj
61
+
62
+ def hash_start(key)
63
+ end
64
+
65
+ def hash_end(key)
66
+ end
67
+
68
+ def array_start(key)
69
+ end
70
+
71
+ def array_end(key)
72
+ end
73
+
74
+ def add_value(value, key)
75
+ end
76
+ end # AllSaj
77
+
78
+ no_handler = Object.new()
79
+ all_handler = AllSaj.new()
80
+
81
+ if $verbose
82
+ puts "json:\n#{$json}\n"
83
+ end
84
+
85
+ ### Validate ######################
86
+ p_val = Oj::Parser.new(:validate)
87
+
88
+ puts '-' * 80
89
+ puts 'Validate Performance'
90
+ perf = Perf.new()
91
+ perf.add('Oj::Parser.validate', 'none') { p_val.parse($json) }
92
+ perf.add('Oj::Saj.none', 'none') { Oj.saj_parse(no_handler, $json) }
93
+ perf.run($iter)
94
+
95
+ ### SAJ ######################
96
+ p_all = Oj::Parser.new(:saj)
97
+ p_all.handler = all_handler
98
+ p_all.cache_keys = $cache_keys
99
+ p_all.cache_strings = 6
100
+
101
+ puts '-' * 80
102
+ puts 'Parse Callback Performance'
103
+ perf = Perf.new()
104
+ perf.add('Oj::Parser.saj', 'all') { p_all.parse($json) }
105
+ perf.add('Oj::Saj.all', 'all') { Oj.saj_parse(all_handler, $json) }
106
+ perf.run($iter)
107
+
108
+ ### Usual ######################
109
+ p_usual = Oj::Parser.new(:usual)
110
+ p_usual.cache_keys = $cache_keys
111
+ p_usual.cache_strings = ($cache_keys ? 6 : 0)
112
+ p_usual.symbol_keys = $symbol_keys
113
+
114
+ puts '-' * 80
115
+ puts 'Parse Usual Performance'
116
+ perf = Perf.new()
117
+ perf.add('Oj::Parser.usual', '') { p_usual.parse($json) }
118
+ perf.add('Oj::strict_load', '') { Oj.strict_load($json) }
119
+ perf.add('JSON::Ext', 'parse') { JSON.parse($json) }
120
+ perf.run($iter)
121
+
122
+ ### Usual Objects ######################
123
+
124
+ # Original Oj follows the JSON gem for creating objects which uses the class
125
+ # json_create(arg) method. Oj::Parser in usual mode supprts the same but also
126
+ # handles populating the object variables directly which is faster.
127
+
128
+ class Stuff
129
+ attr_accessor :alpha, :bravo, :charlie, :delta, :echo, :foxtrot, :golf, :hotel, :india, :juliet
130
+
131
+ def self.json_create(arg)
132
+ obj = new
133
+ obj.alpha = arg['alpha']
134
+ obj.bravo = arg['bravo']
135
+ obj.charlie = arg['charlie']
136
+ obj.delta = arg['delta']
137
+ obj.echo = arg['echo']
138
+ obj.foxtrot = arg['foxtrot']
139
+ obj.golf = arg['golf']
140
+ obj.hotel = arg['hotel']
141
+ obj.india = arg['india']
142
+ obj.juliet = arg['juliet']
143
+ obj
144
+ end
145
+ end
146
+
147
+ $obj_json = %|{
148
+ "alpha": [0, 1,2,3,4,5,6,7,8,9],
149
+ "bravo": true,
150
+ "charlie": 123,
151
+ "delta": "some string",
152
+ "echo": null,
153
+ "^": "Stuff",
154
+ "foxtrot": false,
155
+ "golf": "gulp",
156
+ "hotel": {"x": true, "y": false},
157
+ "india": [null, true, 123],
158
+ "juliet": "junk"
159
+ }|
160
+
161
+ p_usual = Oj::Parser.new(:usual)
162
+ p_usual.cache_keys = $cache_keys
163
+ p_usual.cache_strings = ($cache_keys ? 6 : 0)
164
+ p_usual.symbol_keys = $symbol_keys
165
+ p_usual.create_id = '^'
166
+ p_usual.class_cache = true
167
+ p_usual.ignore_json_create = true
168
+
169
+ JSON.create_id = '^'
170
+
171
+ puts '-' * 80
172
+ puts 'Parse Usual Object Performance'
173
+ perf = Perf.new()
174
+ perf.add('Oj::Parser.usual', '') { p_usual.parse($obj_json) }
175
+ perf.add('Oj::compat_load', '') { Oj.compat_load($obj_json) }
176
+ perf.add('JSON::Ext', 'parse') { JSON.parse($obj_json) }
177
+
178
+ perf.run($iter)
179
+
180
+ unless $failed.empty?
181
+ puts 'The following packages were not included for the reason listed'
182
+ $failed.each { |tag, msg| puts "***** #{tag}: #{msg}" }
183
+ end
data/test/perf_saj.rb CHANGED
@@ -1,40 +1,37 @@
1
1
  #!/usr/bin/env ruby -wW1
2
- # encoding: UTF-8
2
+ # frozen_string_literal: true
3
3
 
4
- $: << '.'
5
- $: << File.join(File.dirname(__FILE__), "../lib")
6
- $: << File.join(File.dirname(__FILE__), "../ext")
4
+ $LOAD_PATH << '.'
5
+ $LOAD_PATH << File.join(__dir__, '../lib')
6
+ $LOAD_PATH << File.join(__dir__, '../ext')
7
7
 
8
8
  require 'optparse'
9
- require 'yajl'
9
+ # require 'yajl'
10
10
  require 'perf'
11
11
  require 'json'
12
12
  require 'json/ext'
13
13
  require 'oj'
14
14
 
15
- $verbose = false
16
- $indent = 0
17
- $iter = 10000
18
- $gets = 0
19
- $fetch = false
20
- $write = false
21
- $read = false
15
+ @verbose = false
16
+ @indent = 0
17
+ @iter = 10_000
18
+ @gets = 0
19
+ @fetch = false
20
+ @write = false
21
+ @read = false
22
22
 
23
23
  opts = OptionParser.new
24
- opts.on("-v", "verbose") { $verbose = true }
25
- opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
26
- opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
27
- opts.on("-g", "--gets [Int]", Integer, "number of gets") { |i| $gets = i }
28
- opts.on("-f", "fetch") { $fetch = true }
29
- opts.on("-w", "write") { $write = true }
30
- opts.on("-r", "read") { $read = true }
31
- opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
32
- files = opts.parse(ARGV)
24
+ opts.on('-v', 'verbose') { @verbose = true }
25
+ opts.on('-c', '--count [Int]', Integer, 'iterations') { |i| @iter = i }
26
+ opts.on('-i', '--indent [Int]', Integer, 'indentation') { |i| @indent = i }
27
+ opts.on('-g', '--gets [Int]', Integer, 'number of gets') { |i| @gets = i }
28
+ opts.on('-f', 'fetch') { @fetch = true }
29
+ opts.on('-w', 'write') { @write = true }
30
+ opts.on('-r', 'read') { @read = true }
31
+ opts.on('-h', '--help', 'Show this display') { puts opts; Process.exit!(0) }
32
+ opts.parse(ARGV)
33
33
 
34
34
  class AllSaj < Oj::Saj
35
- def initialize()
36
- end
37
-
38
35
  def hash_start(key)
39
36
  end
40
37
 
@@ -52,58 +49,53 @@ class AllSaj < Oj::Saj
52
49
  end # AllSaj
53
50
 
54
51
  class NoSaj < Oj::Saj
55
- def initialize()
56
- end
57
52
  end # NoSaj
58
53
 
59
54
  saj_handler = AllSaj.new()
60
55
  no_saj = NoSaj.new()
61
56
 
62
- $obj = {
57
+ @obj = {
63
58
  'a' => 'Alpha', # string
64
59
  'b' => true, # boolean
65
- 'c' => 12345, # number
66
- 'd' => [ true, [false, {'12345' => 12345, 'nil' => nil}, 3.967, { 'x' => 'something', 'y' => false, 'z' => true}, nil]], # mix it up array
60
+ 'c' => 12_345, # number
61
+ 'd' => [ true, [false, {'12345' => 12_345, 'nil' => nil}, 3.967, { 'x' => 'something', 'y' => false, 'z' => true}, nil]], # mix it up array
67
62
  'e' => { 'one' => 1, 'two' => 2 }, # hash
68
63
  'f' => nil, # nil
69
- 'g' => 12345678901234567890123456789, # big number
64
+ 'g' => 12_345_678_901_234_567_890_123_456_789, # big number
70
65
  'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
71
66
  'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
72
67
  }
73
68
 
74
- Oj.default_options = { :indent => $indent, :mode => :compat }
69
+ Oj.default_options = { :indent => @indent, :mode => :compat }
75
70
 
76
- $json = Oj.dump($obj)
77
- $failed = {} # key is same as String used in tests later
71
+ @json = Oj.dump(@obj)
72
+ @failed = {} # key is same as String used in tests later
78
73
 
79
74
  def capture_error(tag, orig, load_key, dump_key, &blk)
80
- begin
81
- obj = blk.call(orig)
82
- raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
83
- rescue Exception => e
84
- $failed[tag] = "#{e.class}: #{e.message}"
85
- end
75
+ obj = blk.call(orig)
76
+ raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
77
+ rescue Exception => e
78
+ @failed[tag] = "#{e.class}: #{e.message}"
86
79
  end
87
80
 
88
81
  # Verify that all packages dump and load correctly and return the same Object as the original.
89
- capture_error('Yajl', $obj, 'encode', 'parse') { |o| Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
90
- capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o| JSON.generator = JSON::Ext::Generator; JSON::Ext::Parser.new(JSON.generate(o)).parse }
82
+ # capture_error('Yajl', @obj, 'encode', 'parse') { |o| Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
83
+ capture_error('JSON::Ext', @obj, 'generate', 'parse') { |o| JSON.generator = JSON::Ext::Generator; JSON::Ext::Parser.new(JSON.generate(o)).parse }
91
84
 
92
- if $verbose
93
- puts "json:\n#{$json}\n"
85
+ if @verbose
86
+ puts "json:\n#{@json}\n"
94
87
  end
95
88
 
96
-
97
89
  puts '-' * 80
98
- puts "Parse Performance"
90
+ puts 'Parse Performance'
99
91
  perf = Perf.new()
100
- perf.add('Oj::Saj', 'all') { Oj.saj_parse(saj_handler, $json) }
101
- perf.add('Oj::Saj', 'none') { Oj.saj_parse(no_saj, $json) }
102
- perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
103
- perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new($json).parse } unless $failed.has_key?('JSON::Ext')
104
- perf.run($iter)
105
-
106
- unless $failed.empty?
107
- puts "The following packages were not included for the reason listed"
108
- $failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
92
+ perf.add('Oj::Saj', 'all') { Oj.saj_parse(saj_handler, @json) }
93
+ perf.add('Oj::Saj', 'none') { Oj.saj_parse(no_saj, @json) }
94
+ # perf.add('Yajl', 'parse') { Yajl::Parser.parse(@json) } unless @failed.has_key?('Yajl')
95
+ perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new(@json).parse } unless @failed.key?('JSON::Ext')
96
+ perf.run(@iter)
97
+
98
+ unless @failed.empty?
99
+ puts 'The following packages were not included for the reason listed'
100
+ @failed.each { |tag, msg| puts "***** #{tag}: #{msg}" }
109
101
  end