oj 2.0.14 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +47 -332
- data/ext/oj/buf.h +103 -0
- data/ext/oj/circarray.c +93 -0
- data/ext/oj/circarray.h +48 -0
- data/ext/oj/compat.c +112 -0
- data/ext/oj/dump.c +2 -1
- data/ext/oj/err.c +82 -0
- data/ext/oj/err.h +64 -0
- data/ext/oj/extconf.rb +1 -0
- data/ext/oj/hash.c +149 -0
- data/ext/oj/{cache.h → hash.h} +9 -10
- data/ext/oj/hash_test.c +501 -0
- data/ext/oj/object.c +514 -0
- data/ext/oj/odd.c +159 -0
- data/ext/oj/odd.h +61 -0
- data/ext/oj/oj.c +235 -305
- data/ext/oj/oj.h +18 -23
- data/ext/oj/parse.c +798 -0
- data/ext/oj/parse.h +88 -0
- data/ext/oj/resolve.c +117 -0
- data/ext/oj/resolve.h +38 -0
- data/ext/oj/saj.c +58 -86
- data/ext/oj/scp.c +308 -0
- data/ext/oj/strict.c +166 -0
- data/ext/oj/val_stack.c +48 -0
- data/ext/oj/val_stack.h +167 -0
- data/lib/oj.rb +1 -0
- data/lib/oj/saj.rb +11 -8
- data/lib/oj/schandler.rb +70 -0
- data/lib/oj/version.rb +1 -1
- data/test/bug.rb +14 -22
- data/test/perf_compat.rb +128 -0
- data/test/{perf_obj.rb → perf_object.rb} +18 -6
- data/test/perf_scp.rb +151 -0
- data/test/perf_strict.rb +23 -122
- data/test/sample.rb +2 -2
- data/test/test_compat.rb +342 -0
- data/test/test_object.rb +390 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +224 -0
- data/test/test_strict.rb +250 -0
- data/test/tests.rb +8 -18
- metadata +31 -10
- data/ext/oj/cache.c +0 -148
- data/ext/oj/load.c +0 -1089
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
data/lib/oj/version.rb
CHANGED
data/test/bug.rb
CHANGED
@@ -1,25 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
1
12
|
|
2
|
-
require 'pp'
|
3
13
|
require 'oj'
|
4
14
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
\"author\": {\"additionalType\":\"http://getfetcher.net/Item\",
|
9
|
-
\"id\":1054045717,
|
10
|
-
\"name\":\"i'm natriznator\",
|
11
|
-
\"dateRegistered\":{\"^t\":1357095124.000000000},
|
12
|
-
\"description\":\"menos falsidade e mais liberdade\",
|
13
|
-
\"url\":\"https://twitter.com/hotlov4to\"},
|
14
|
-
\"viewer\": {\"additionalType\":\"http://getfetcher.net/Item\",
|
15
|
-
\"id\":861875166,
|
16
|
-
\"name\":\"Fetcher Dev\",
|
17
|
-
\"dateRegistered\":{\"^t\":1349377226.000000000},
|
18
|
-
\"description\":null,
|
19
|
-
\"url\":\"https://twitter.com/FetcherDev\"},
|
20
|
-
\"dateCreated\": {\"^t\":1361225690.000000000},
|
21
|
-
\"provider\": [\"twitter\",
|
22
|
-
\"web\"],
|
23
|
-
\"url\": \"https://twitter.com/hotlov4to/status/303628670768128001\",
|
24
|
-
\"_id\": {\"^o\":\"BSON::ObjectId\",
|
25
|
-
\"data\":[81,34,167,251,70,246,92,80,135,0,0,1]}}", :auto_define => false)
|
15
|
+
n = 17572
|
16
|
+
Oj.strict_load('[' * n + ']' * n)
|
17
|
+
|
data/test/perf_compat.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << '.'
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
require 'perf'
|
10
|
+
require 'oj'
|
11
|
+
|
12
|
+
$verbose = false
|
13
|
+
$indent = 0
|
14
|
+
$iter = 20000
|
15
|
+
$with_bignum = false
|
16
|
+
$with_nums = true
|
17
|
+
$size = 0
|
18
|
+
|
19
|
+
opts = OptionParser.new
|
20
|
+
opts.on("-v", "verbose") { $verbose = true }
|
21
|
+
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
22
|
+
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
23
|
+
opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
|
24
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
25
|
+
files = opts.parse(ARGV)
|
26
|
+
|
27
|
+
module One
|
28
|
+
module Two
|
29
|
+
module Three
|
30
|
+
class Empty
|
31
|
+
|
32
|
+
def initialize()
|
33
|
+
end
|
34
|
+
|
35
|
+
def eql?(o)
|
36
|
+
self.class == o.class
|
37
|
+
end
|
38
|
+
alias == eql?
|
39
|
+
|
40
|
+
def to_hash()
|
41
|
+
{'json_class' => "#{self.class.name}"}
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_json(*a)
|
45
|
+
%{{"json_class":"#{self.class.name}"}}
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.json_create(h)
|
49
|
+
self.new()
|
50
|
+
end
|
51
|
+
end # Empty
|
52
|
+
end # Three
|
53
|
+
end # Two
|
54
|
+
end # One
|
55
|
+
|
56
|
+
$obj = {
|
57
|
+
'a' => 'Alpha', # string
|
58
|
+
'b' => true, # boolean
|
59
|
+
'c' => 12345, # number
|
60
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
61
|
+
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
62
|
+
'f' => nil, # nil
|
63
|
+
'g' => One::Two::Three::Empty.new(),
|
64
|
+
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
65
|
+
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
66
|
+
}
|
67
|
+
|
68
|
+
Oj.default_options = { :indent => $indent, :mode => :compat }
|
69
|
+
|
70
|
+
if 0 < $size
|
71
|
+
s = Oj.dump($obj, :mode => :compat).size + 1
|
72
|
+
cnt = $size * 1024 / s
|
73
|
+
o = $obj
|
74
|
+
$obj = []
|
75
|
+
cnt.times do
|
76
|
+
$obj << o
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
$json = Oj.dump($obj, :mode => :compat)
|
81
|
+
$failed = {} # key is same as String used in tests later
|
82
|
+
|
83
|
+
def capture_error(tag, orig, load_key, dump_key, &blk)
|
84
|
+
begin
|
85
|
+
obj = blk.call(orig)
|
86
|
+
raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
|
87
|
+
rescue Exception => e
|
88
|
+
$failed[tag] = "#{e.class}: #{e.message}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Verify that all packages dump and load correctly and return the same Object as the original.
|
93
|
+
capture_error('Oj:compat', $obj, 'load', 'dump') { |o| Oj.compat_load(Oj.dump(o, :mode => :compat)) }
|
94
|
+
capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
|
95
|
+
require 'json'
|
96
|
+
require 'json/ext'
|
97
|
+
JSON.generator = JSON::Ext::Generator
|
98
|
+
JSON.parser = JSON::Ext::Parser
|
99
|
+
JSON.load(JSON.generate(o))
|
100
|
+
}
|
101
|
+
|
102
|
+
if $verbose
|
103
|
+
puts "size: #{$json.size}"
|
104
|
+
puts "json:\n#{$json}\n"
|
105
|
+
puts "Oj:compat loaded object:\n#{Oj.compat_load($json)}\n"
|
106
|
+
puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
|
107
|
+
end
|
108
|
+
|
109
|
+
puts '-' * 80
|
110
|
+
puts "Compat Parse Performance"
|
111
|
+
perf = Perf.new()
|
112
|
+
unless $failed.has_key?('JSON::Ext')
|
113
|
+
perf.add('JSON::Ext', 'parse') { JSON.load($json) }
|
114
|
+
perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
|
115
|
+
end
|
116
|
+
unless $failed.has_key?('Oj:compat')
|
117
|
+
perf.add('Oj:compat', 'compat_load') { Oj.compat_load($json) }
|
118
|
+
end
|
119
|
+
perf.run($iter)
|
120
|
+
|
121
|
+
puts
|
122
|
+
puts '-' * 80
|
123
|
+
puts
|
124
|
+
|
125
|
+
unless $failed.empty?
|
126
|
+
puts "The following packages were not included for the reason listed"
|
127
|
+
$failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
|
128
|
+
end
|
@@ -29,10 +29,13 @@ do_dump = false
|
|
29
29
|
do_read = false
|
30
30
|
do_write = false
|
31
31
|
$iter = 1000
|
32
|
+
$mult = 1
|
32
33
|
|
33
34
|
opts = OptionParser.new
|
34
35
|
opts.on("-c", "circular options") { $circular = true }
|
35
36
|
|
37
|
+
opts.on("-x", "use sample instead of files") { do_sample = true }
|
38
|
+
|
36
39
|
opts.on("-s", "load and dump as sample Ruby object") { do_sample = true }
|
37
40
|
opts.on("-f", "load and dump as files Ruby object") { do_files = true }
|
38
41
|
|
@@ -43,6 +46,7 @@ opts.on("-w", "write") { do_write = true }
|
|
43
46
|
opts.on("-a", "load, dump, read and write") { do_load = true; do_dump = true; do_read = true; do_write = true }
|
44
47
|
|
45
48
|
opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i }
|
49
|
+
opts.on("-m", "--multiply [Int]", Integer, "multiplier") { |i| $mult = i }
|
46
50
|
|
47
51
|
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
48
52
|
files = opts.parse(ARGV)
|
@@ -61,7 +65,11 @@ end
|
|
61
65
|
|
62
66
|
# prepare all the formats for input
|
63
67
|
if files.empty?
|
64
|
-
$obj =
|
68
|
+
$obj = []
|
69
|
+
$mult.times do
|
70
|
+
$obj << (do_sample ? sample_doc(2) : files('..'))
|
71
|
+
end
|
72
|
+
|
65
73
|
$mars = Marshal.dump($obj)
|
66
74
|
$xml = Ox.dump($obj, :indent => $indent, :circular => $circular)
|
67
75
|
$json = Oj.dump($obj, :indent => $indent, :circular => $circular)
|
@@ -75,18 +83,22 @@ else
|
|
75
83
|
$xml = File.read(f)
|
76
84
|
$obj = Ox.load($xml);
|
77
85
|
$mars = Marshal.dump($obj)
|
78
|
-
$json = Oj.dump($obj, :indent => $indent, circular
|
86
|
+
$json = Oj.dump($obj, :indent => $indent, :circular => $circular)
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
82
90
|
Oj.default_options = { :mode => :object, :indent => $indent, :circular => $circular }
|
91
|
+
#puts "json: #{$json.size}"
|
92
|
+
#puts "xml: #{$xml.size}"
|
93
|
+
#puts "marshal: #{$mars.size}"
|
94
|
+
|
83
95
|
|
84
96
|
if do_load
|
85
97
|
puts '-' * 80
|
86
98
|
puts "Load Performance"
|
87
99
|
perf = Perf.new()
|
100
|
+
perf.add('Oj.object', 'load') { Oj.object_load($json) }
|
88
101
|
perf.add('Ox', 'load') { Ox.load($xml, :mode => :object) }
|
89
|
-
perf.add('Oj', 'load') { Oj.load($json) }
|
90
102
|
perf.add('Marshal', 'load') { Marshal.load($mars) }
|
91
103
|
perf.run($iter)
|
92
104
|
end
|
@@ -95,8 +107,8 @@ if do_dump
|
|
95
107
|
puts '-' * 80
|
96
108
|
puts "Dump Performance"
|
97
109
|
perf = Perf.new()
|
98
|
-
perf.add('Ox', 'dump') { Ox.dump($obj, :indent => $indent, :circular => $circular) }
|
99
110
|
perf.add('Oj', 'dump') { Oj.dump($obj) }
|
111
|
+
perf.add('Ox', 'dump') { Ox.dump($obj, :indent => $indent, :circular => $circular) }
|
100
112
|
perf.add('Marshal', 'dump') { Marshal.dump($obj) }
|
101
113
|
perf.run($iter)
|
102
114
|
end
|
@@ -105,8 +117,8 @@ if do_read
|
|
105
117
|
puts '-' * 80
|
106
118
|
puts "Read from file Performance"
|
107
119
|
perf = Perf.new()
|
108
|
-
perf.add('Ox', 'load_file') { Ox.load_file('sample.xml', :mode => :object) }
|
109
120
|
perf.add('Oj', 'load') { Oj.load_file('sample.json') }
|
121
|
+
perf.add('Ox', 'load_file') { Ox.load_file('sample.xml', :mode => :object) }
|
110
122
|
perf.add('Marshal', 'load') { Marshal.load(File.new('sample.marshal')) }
|
111
123
|
perf.run($iter)
|
112
124
|
end
|
@@ -115,8 +127,8 @@ if do_write
|
|
115
127
|
puts '-' * 80
|
116
128
|
puts "Write to file Performance"
|
117
129
|
perf = Perf.new()
|
118
|
-
perf.add('Ox', 'to_file') { Ox.to_file('sample.xml', $obj, :indent => $indent, :circular => $circular) }
|
119
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) }
|
120
132
|
perf.add('Marshal', 'dump') { Marshal.dump($obj, File.new('sample.marshal', 'w')) }
|
121
133
|
perf.run($iter)
|
122
134
|
end
|
data/test/perf_scp.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << '.'
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
require 'yajl'
|
10
|
+
require 'perf'
|
11
|
+
require 'json'
|
12
|
+
require 'json/ext'
|
13
|
+
require 'oj'
|
14
|
+
|
15
|
+
$verbose = false
|
16
|
+
$indent = 0
|
17
|
+
$iter = 50000
|
18
|
+
$with_bignum = false
|
19
|
+
$size = 0
|
20
|
+
|
21
|
+
opts = OptionParser.new
|
22
|
+
opts.on("-v", "verbose") { $verbose = true }
|
23
|
+
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
24
|
+
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
25
|
+
opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
|
26
|
+
opts.on("-b", "with bignum") { $with_bignum = true }
|
27
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
28
|
+
files = opts.parse(ARGV)
|
29
|
+
|
30
|
+
$obj = {
|
31
|
+
'a' => 'Alpha', # string
|
32
|
+
'b' => true, # boolean
|
33
|
+
'c' => 12345, # number
|
34
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], 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'] = 12345678901234567890123456789 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
|
+
Oj.default_options = { :indent => $indent, :mode => :compat }
|
51
|
+
|
52
|
+
$json = Oj.dump($obj)
|
53
|
+
$failed = {} # key is same as String used in tests later
|
54
|
+
|
55
|
+
class AllSaj < Oj::Saj
|
56
|
+
def initialize()
|
57
|
+
end
|
58
|
+
|
59
|
+
def hash_start(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
def hash_end(key)
|
63
|
+
end
|
64
|
+
|
65
|
+
def array_start(key)
|
66
|
+
end
|
67
|
+
|
68
|
+
def array_end(key)
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_value(value, key)
|
72
|
+
end
|
73
|
+
end # AllSaj
|
74
|
+
|
75
|
+
class NoSaj < Oj::Saj
|
76
|
+
def initialize()
|
77
|
+
end
|
78
|
+
end # NoSaj
|
79
|
+
|
80
|
+
class NoHandler < Oj::ScHandler
|
81
|
+
def initialize()
|
82
|
+
end
|
83
|
+
end # NoHandler
|
84
|
+
|
85
|
+
class AllHandler < Oj::ScHandler
|
86
|
+
def initialize()
|
87
|
+
end
|
88
|
+
|
89
|
+
def hash_start()
|
90
|
+
return nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def hash_end()
|
94
|
+
end
|
95
|
+
|
96
|
+
def array_start()
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def array_end()
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_value(value)
|
104
|
+
end
|
105
|
+
|
106
|
+
def hash_set(h, key, value)
|
107
|
+
end
|
108
|
+
|
109
|
+
def array_append(a, value)
|
110
|
+
end
|
111
|
+
|
112
|
+
end # AllHandler
|
113
|
+
|
114
|
+
saj_handler = AllSaj.new()
|
115
|
+
no_saj = NoSaj.new()
|
116
|
+
|
117
|
+
sc_handler = AllHandler.new()
|
118
|
+
no_handler = NoHandler.new()
|
119
|
+
|
120
|
+
def capture_error(tag, orig, load_key, dump_key, &blk)
|
121
|
+
begin
|
122
|
+
obj = blk.call(orig)
|
123
|
+
raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
|
124
|
+
rescue Exception => e
|
125
|
+
$failed[tag] = "#{e.class}: #{e.message}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Verify that all packages dump and load correctly and return the same Object as the original.
|
130
|
+
capture_error('Yajl', $obj, 'encode', 'parse') { |o| Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
|
131
|
+
capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o| JSON.generator = JSON::Ext::Generator; JSON::Ext::Parser.new(JSON.generate(o)).parse }
|
132
|
+
|
133
|
+
if $verbose
|
134
|
+
puts "json:\n#{$json}\n"
|
135
|
+
end
|
136
|
+
|
137
|
+
puts '-' * 80
|
138
|
+
puts "Parse Performance"
|
139
|
+
perf = Perf.new()
|
140
|
+
perf.add('Oj::Saj', 'all') { Oj.saj_parse(saj_handler, $json) }
|
141
|
+
perf.add('Oj::Saj', 'none') { Oj.saj_parse(no_saj, $json) }
|
142
|
+
perf.add('Oj::Scp', 'all') { Oj.sc_parse(sc_handler, $json) }
|
143
|
+
perf.add('Oj::Scp', 'none') { Oj.sc_parse(no_handler, $json) }
|
144
|
+
perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
|
145
|
+
perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new($json).parse } unless $failed.has_key?('JSON::Ext')
|
146
|
+
perf.run($iter)
|
147
|
+
|
148
|
+
unless $failed.empty?
|
149
|
+
puts "The following packages were not included for the reason listed"
|
150
|
+
$failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
|
151
|
+
end
|
data/test/perf_strict.rb
CHANGED
@@ -6,76 +6,22 @@ $: << File.join(File.dirname(__FILE__), "../lib")
|
|
6
6
|
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
7
|
|
8
8
|
require 'optparse'
|
9
|
-
#require 'yajl'
|
10
9
|
require 'perf'
|
11
|
-
#require 'json'
|
12
|
-
#require 'json/pure'
|
13
|
-
#require 'json/ext'
|
14
|
-
#require 'msgpack'
|
15
10
|
require 'oj'
|
16
|
-
#require 'ox'
|
17
|
-
|
18
|
-
class Jazz
|
19
|
-
attr_accessor :boolean, :number, :string
|
20
|
-
|
21
|
-
def initialize()
|
22
|
-
@boolean = true
|
23
|
-
@number = 58
|
24
|
-
@string = "A string"
|
25
|
-
end
|
26
|
-
|
27
|
-
def eql?(o)
|
28
|
-
(self.class == o.class &&
|
29
|
-
boolean == o.boolean &&
|
30
|
-
number == o.number &&
|
31
|
-
string == o.string)
|
32
|
-
end
|
33
|
-
alias == eql?
|
34
|
-
|
35
|
-
def to_json(*) # Yajl and JSON have different signatures
|
36
|
-
%{
|
37
|
-
{ "json_class":"Jazz",
|
38
|
-
"boolean":#{@boolean},
|
39
|
-
"number":#{@number},
|
40
|
-
"string":"#{@string}"
|
41
|
-
}}
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_hash()
|
45
|
-
{ 'json_class' => "Jazz",
|
46
|
-
'boolean' => @boolean,
|
47
|
-
'number' => @number,
|
48
|
-
'string' => @string
|
49
|
-
}
|
50
|
-
end
|
51
|
-
alias as_json to_hash
|
52
|
-
|
53
|
-
def to_msgpack(out='')
|
54
|
-
to_hash().to_msgpack(out)
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.json_create(h)
|
58
|
-
j = self.new()
|
59
|
-
j.instance_variable_set(:@boolean, h['boolean'])
|
60
|
-
j.instance_variable_set(:@number, h['number'])
|
61
|
-
j.instance_variable_set(:@string, h['string'])
|
62
|
-
j
|
63
|
-
end
|
64
|
-
end
|
65
11
|
|
66
12
|
$verbose = false
|
67
13
|
$indent = 0
|
68
|
-
$iter =
|
69
|
-
$
|
70
|
-
$with_bignum = true
|
14
|
+
$iter = 20000
|
15
|
+
$with_bignum = false
|
71
16
|
$with_nums = true
|
17
|
+
$size = 0
|
72
18
|
|
73
19
|
opts = OptionParser.new
|
74
20
|
opts.on("-v", "verbose") { $verbose = true }
|
75
21
|
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
76
22
|
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
77
|
-
opts.on("-
|
78
|
-
opts.on("-b", "
|
23
|
+
opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
|
24
|
+
opts.on("-b", "with bignum") { $with_bignum = true }
|
79
25
|
opts.on("-n", "without numbers") { $with_nums = false }
|
80
26
|
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
81
27
|
files = opts.parse(ARGV)
|
@@ -85,10 +31,9 @@ if $with_nums
|
|
85
31
|
'a' => 'Alpha', # string
|
86
32
|
'b' => true, # boolean
|
87
33
|
'c' => 12345, # number
|
88
|
-
'd' => [ true, [false, [
|
89
|
-
'e' => { 'one' => 1, 'two' => 2 }, # hash
|
34
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
35
|
+
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
90
36
|
'f' => nil, # nil
|
91
|
-
#'g' => 12345678901234567890123456789, # big number
|
92
37
|
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
93
38
|
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
94
39
|
}
|
@@ -99,18 +44,26 @@ else
|
|
99
44
|
'b' => true,
|
100
45
|
'c' => '12345',
|
101
46
|
'd' => [ true, [false, ['12345', nil], '3.967', ['something', false], nil]],
|
102
|
-
'e' => { 'one' => '1', 'two' => '2' },
|
47
|
+
'e' => { 'zero' => '0', 'one' => '1', 'two' => '2' },
|
103
48
|
'f' => nil,
|
104
49
|
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
105
50
|
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
106
51
|
}
|
107
52
|
end
|
108
|
-
$obj['j'] = Jazz.new() if $with_object
|
109
53
|
|
110
|
-
Oj.default_options = { :indent => $indent, :mode => :
|
54
|
+
Oj.default_options = { :indent => $indent, :mode => :strict }
|
55
|
+
|
56
|
+
if 0 < $size
|
57
|
+
o = $obj
|
58
|
+
$obj = []
|
59
|
+
(4 * $size).times do
|
60
|
+
$obj << o
|
61
|
+
end
|
62
|
+
end
|
111
63
|
|
112
64
|
$json = Oj.dump($obj)
|
113
65
|
$obj_json = Oj.dump($obj, :mode => :object)
|
66
|
+
#puts "*** size: #{$obj_json.size}"
|
114
67
|
$failed = {} # key is same as String used in tests later
|
115
68
|
|
116
69
|
def capture_error(tag, orig, load_key, dump_key, &blk)
|
@@ -123,15 +76,7 @@ def capture_error(tag, orig, load_key, dump_key, &blk)
|
|
123
76
|
end
|
124
77
|
|
125
78
|
# Verify that all packages dump and load correctly and return the same Object as the original.
|
126
|
-
capture_error('Oj:
|
127
|
-
capture_error('Oj', $obj, 'load', 'dump') { |o| Oj.load(Oj.dump(o, :mode => :compat), :mode => :compat) }
|
128
|
-
capture_error('Ox', $obj, 'load', 'dump') { |o|
|
129
|
-
require 'ox'
|
130
|
-
Ox.default_options = { :indent => $indent, :mode => :object }
|
131
|
-
$xml = Ox.dump($obj, :indent => $indent)
|
132
|
-
Ox.load(Ox.dump(o, :mode => :object), :mode => :object)
|
133
|
-
}
|
134
|
-
capture_error('MessagePack', $obj, 'unpack', 'pack') { |o| require 'msgpack'; MessagePack.unpack(MessagePack.pack($obj)) }
|
79
|
+
capture_error('Oj:strict', $obj, 'load', 'dump') { |o| Oj.strict_load(Oj.dump(o, :mode => :strict)) }
|
135
80
|
capture_error('Yajl', $obj, 'encode', 'parse') { |o| require 'yajl'; Yajl::Parser.parse(Yajl::Encoder.encode(o)) }
|
136
81
|
capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
|
137
82
|
require 'json'
|
@@ -147,22 +92,16 @@ capture_error('JSON::Pure', $obj, 'generate', 'parse') { |o|
|
|
147
92
|
JSON.parse(JSON.generate(o))
|
148
93
|
}
|
149
94
|
|
150
|
-
begin
|
151
|
-
$msgpack = MessagePack.pack($obj)
|
152
|
-
rescue Exception => e
|
153
|
-
$msgpack = nil
|
154
|
-
end
|
155
|
-
|
156
95
|
if $verbose
|
157
96
|
puts "json:\n#{$json}\n"
|
158
97
|
puts "object json:\n#{$obj_json}\n"
|
159
|
-
puts "Oj loaded object:\n#{Oj.
|
98
|
+
puts "Oj loaded object:\n#{Oj.strict_load($json)}\n"
|
160
99
|
puts "Yajl loaded object:\n#{Yajl::Parser.parse($json)}\n"
|
161
100
|
puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
|
162
101
|
end
|
163
102
|
|
164
103
|
puts '-' * 80
|
165
|
-
puts "
|
104
|
+
puts "Strict Parse Performance"
|
166
105
|
perf = Perf.new()
|
167
106
|
unless $failed.has_key?('JSON::Ext')
|
168
107
|
perf.add('JSON::Ext', 'parse') { JSON.parse($json) }
|
@@ -172,52 +111,14 @@ unless $failed.has_key?('JSON::Pure')
|
|
172
111
|
perf.add('JSON::Pure', 'parse') { JSON.parse($json) }
|
173
112
|
perf.before('JSON::Pure') { JSON.parser = JSON::Pure::Parser }
|
174
113
|
end
|
175
|
-
unless $failed.has_key?('Oj:
|
176
|
-
perf.add('Oj:
|
177
|
-
perf.before('Oj:compat') { Oj.default_options = { :mode => :compat} }
|
178
|
-
end
|
179
|
-
unless $failed.has_key?('Oj')
|
180
|
-
perf.add('Oj', 'load') { Oj.load($obj_json) }
|
181
|
-
perf.before('Oj') { Oj.default_options = { :mode => :object} }
|
114
|
+
unless $failed.has_key?('Oj:strict')
|
115
|
+
perf.add('Oj:strict', 'strict_load') { Oj.strict_load($json) }
|
182
116
|
end
|
183
117
|
perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
|
184
|
-
perf.add('Ox', 'load') { Ox.load($xml) } unless $failed.has_key?('Ox')
|
185
|
-
perf.add('MessagePack', 'unpack') { MessagePack.unpack($msgpack) } unless $failed.has_key?('MessagePack')
|
186
118
|
perf.run($iter)
|
187
119
|
|
188
120
|
puts
|
189
121
|
puts '-' * 80
|
190
|
-
puts "Dump/Encode/Generate Performance"
|
191
|
-
perf = Perf.new()
|
192
|
-
unless $failed.has_key?('JSON::Ext')
|
193
|
-
if 0 == $indent
|
194
|
-
perf.add('JSON::Ext', 'generate') { JSON.generate($obj) }
|
195
|
-
else
|
196
|
-
perf.add('JSON::Ext', 'generate') { JSON.pretty_generate($obj) }
|
197
|
-
end
|
198
|
-
perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
|
199
|
-
end
|
200
|
-
unless $failed.has_key?('JSON::Pure')
|
201
|
-
if 0 == $indent
|
202
|
-
perf.add('JSON::Pure', 'generate') { JSON.generate($obj) }
|
203
|
-
else
|
204
|
-
perf.add('JSON::Pure', 'generate') { JSON.pretty_generate($obj) }
|
205
|
-
end
|
206
|
-
perf.before('JSON::Pure') { JSON.generator = JSON::Pure::Generator }
|
207
|
-
end
|
208
|
-
unless $failed.has_key?('Oj')
|
209
|
-
perf.add('Oj', 'dump') { Oj.dump($obj) }
|
210
|
-
perf.before('Oj') { Oj.default_options = { :mode => :object} }
|
211
|
-
end
|
212
|
-
unless $failed.has_key?('Oj:compat')
|
213
|
-
perf.add('Oj:compat', 'dump') { Oj.dump($obj) }
|
214
|
-
perf.before('Oj:compat') { Oj.default_options = { :mode => :compat} }
|
215
|
-
end
|
216
|
-
perf.add('Yajl', 'encode') { Yajl::Encoder.encode($obj) } unless $failed.has_key?('Yajl')
|
217
|
-
perf.add('Ox', 'dump') { Ox.dump($obj) } unless $failed.has_key?('Ox')
|
218
|
-
perf.add('MessagePack', 'pack') { MessagePack.pack($obj) } unless $failed.has_key?('MessagePack')
|
219
|
-
perf.run($iter)
|
220
|
-
|
221
122
|
puts
|
222
123
|
|
223
124
|
unless $failed.empty?
|