oj 3.11.5 → 3.16.5

Sign up to get free protection for your applications and to get access to all the features.
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