oj 3.13.0 → 3.13.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/oj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.13.0'
4
+ VERSION = '3.13.4'
5
5
  end
data/pages/Options.md CHANGED
@@ -75,12 +75,22 @@ parse option to match the JSON gem. In that case either `Float`,
75
75
  If true Hash keys are cached or interned. There are trade-offs with
76
76
  caching keys. Large caches will use more memory and in extreme cases
77
77
  (like over a million) the cache may be slower than not using
78
- it. Repeated parsing of similar JSON docs is where cache_keys shines.
78
+ it. Repeated parsing of similar JSON docs is where cache_keys shines
79
+ especially with symbol keys.
80
+
81
+ There is a maximum length for cached keys. Any key longer than 34
82
+ bytes is not cached. Everything still works but the key is not cached.
79
83
 
80
84
  ### :cache_strings [Int]
81
85
 
82
86
  Shorter strings can be cached for better performance. A limit,
83
- cache_strings, defines the upper limit on what strings are cached.
87
+ cache_strings, defines the upper limit on what strings are cached. As
88
+ with cached keys only strings less than 35 bytes are cached even if
89
+ the limit is set higher. Setting the limit to zero effectively
90
+ disables the caching of string values.
91
+
92
+ Note that caching for strings is for string values and not Hash keys
93
+ or Object attributes.
84
94
 
85
95
  ### :circular [Boolean]
86
96
 
@@ -268,7 +278,7 @@ Use symbols instead of strings for hash keys.
268
278
  ### :symbolize_names [Boolean]
269
279
 
270
280
  Like :symbol_keys has keys are made into symbols but only when
271
- mimicing the JSON gem and then only as the JSON gem honors it so
281
+ mimicking the JSON gem and then only as the JSON gem honors it so
272
282
  JSON.parse honors the option but JSON.load does not.
273
283
 
274
284
  ### :trace
data/pages/Parser.md CHANGED
@@ -42,12 +42,12 @@ bleed over to other instances.
42
42
 
43
43
  ## How
44
44
 
45
- It's wonderfull to wish for a faster parser that solves all the
45
+ It's wonderful to wish for a faster parser that solves all the
46
46
  annoyances of the previous parser but how was it done is a much more
47
47
  interesting question to answer.
48
48
 
49
49
  At the core, the API for parsing was changed. Instead of a sinle
50
- global parser any number of parsers can be created and each is seprate
50
+ global parser any number of parsers can be created and each is separate
51
51
  from the others. The parser itself is able to rip through a JSON
52
52
  string, stream, or file and then make calls to a delegate to process
53
53
  the JSON elements according to the delegate behavior. This is similar
@@ -206,7 +206,7 @@ in array creation.
206
206
 
207
207
  For Hash the story is a little different. The bulk insert for Hash
208
208
  alternates keys and values but there is a wrinkle to consider. Since
209
- Ruby Object creation is triggered by the occurance of an element that
209
+ Ruby Object creation is triggered by the occurrence of an element that
210
210
  matches a creation identifier the creation of a collection is not just
211
211
  for Array and Hash but also Object. Setting Object attributes uses an
212
212
  ID and not a VALUE. For that reason the keys should not be created as
data/pages/Rails.md CHANGED
@@ -41,7 +41,7 @@ The globals that ActiveSupport uses for encoding are:
41
41
 
42
42
  Those globals are aliased to also be accessed from the ActiveSupport module
43
43
  directly so `ActiveSupport::JSON::Encoding.time_precision` can also be accessed
44
- from `ActiveSupport.time_precision`. Oj makes use of these globals in mimicing
44
+ from `ActiveSupport.time_precision`. Oj makes use of these globals in mimicking
45
45
  Rails after the `Oj::Rails.set_encode()` method is called. That also sets the
46
46
  `ActiveSupport.json_encoder` to the `Oj::Rails::Encoder` class.
47
47
 
@@ -125,7 +125,7 @@ gem 'oj', '3.7.12'
125
125
  Ruby which is used by the json gem and by Rails. Ruby varies the
126
126
  significant digits which can be either 16 or 17 depending on the value.
127
127
 
128
- 2. Optimized Hashs do not collapse keys that become the same in the output. As
128
+ 2. Optimized Hashes do not collapse keys that become the same in the output. As
129
129
  an example, a non-String object that has a `to_s()` method will become the
130
130
  return value of the `to_s()` method in the output without checking to see if
131
131
  that has already been used. This could occur is a mix of String and Symbols
data/test/benny.rb ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal
3
+
4
+ require 'bundler/inline'
5
+
6
+ gemfile do
7
+ source 'https://rubygems.org'
8
+
9
+ gem 'oj'
10
+ gem 'benchmark-ips', require: 'benchmark/ips'
11
+ end
12
+
13
+ require 'json'
14
+ require 'open-uri'
15
+
16
+ CANADA_DATA_JSON = URI.parse('https://raw.githubusercontent.com/serde-rs/json-benchmark/master/data/canada.json').read
17
+ CANADA_DATA = JSON.parse(CANADA_DATA_JSON)
18
+
19
+ Benchmark.ips do |x|
20
+ x.config(:time => 10, :warmup => 5)
21
+
22
+ x.report("marshall Canada data with Oj") do
23
+ Oj.dump(CANADA_DATA)
24
+ end
25
+
26
+ x.report("marshall Canada data with JSON") do
27
+ JSON.dump(CANADA_DATA)
28
+ end
29
+
30
+ x.compare!
31
+ end
32
+
33
+ Oj.default_options = {
34
+ mode: :strict,
35
+ bigdecimal_load: :fast
36
+ }
37
+
38
+ Benchmark.ips do |x|
39
+ x.config(:time => 10, :warmup => 5)
40
+
41
+ x.report("unmarshall Canada data with Oj") do
42
+ Oj.load(CANADA_DATA_JSON)
43
+ end
44
+
45
+ x.report("unmarshall Canada data with JSON") do
46
+ JSON.parse(CANADA_DATA_JSON)
47
+ end
48
+
49
+ x.compare!
50
+ end
data/test/big.rb ADDED
@@ -0,0 +1,15 @@
1
+ #require 'active_support'
2
+ #require 'active_support/core_ext'
3
+ #require 'active_support/json'
4
+ require 'oj'
5
+
6
+ #Oj.optimize_rails
7
+ Oj.mimic_JSON
8
+
9
+ h = {:type=>:record, :name=>:group, :namespace=>"com.salsify.identity", :fields=>[{:name=>"id", :type=>{:name=>:salsify_uuid, :type=>:fixed, :namespace=>"com.salsify", :size=>38}}, {:name=>"type", :type=>"string", :default=>"groups"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"name", :type=>"string"}, {:name=>"policy", :type=>[:null, {:type=>:record, :name=>:policy, :namespace=>"com.salsify.security", :fields=>[{:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :default=>"policies"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"name", :type=>"string"}, {:name=>"statements", :type=>{:type=>:array, :items=>{:type=>:record, :name=>:statement, :namespace=>"com.salsify.security", :fields=>[{:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :default=>"statements"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"action", :type=>{:name=>"__statement_action_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:manage, :read]}}, {:name=>"resource", :type=>{:name=>"__statement_resource_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:product, :digital_asset]}}, {:name=>"conditions", :type=>{:type=>:array, :items=>{:type=>:record, :name=>:condition, :namespace=>"com.salsify.security", :fields=>[{:name=>"created_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"updated_at", :type=>{:type=>"long", :logicalType=>"timestamp-micros"}}, {:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :default=>"conditions"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}, {:name=>"operator", :type=>{:name=>"__condition_operator_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:equals]}}, {:name=>"attribute_type", :type=>{:name=>"__condition_attribute_type_enum", :type=>:enum, :namespace=>"com.salsify.security", :symbols=>[:resource]}}, {:name=>"value", :type=>"string"}, {:name=>"attribute", :type=>[:null, {:type=>:record, :name=>:reference, :namespace=>"com.salsify", :fields=>[{:name=>"id", :type=>"com.salsify.salsify_uuid"}, {:name=>"type", :type=>"string", :doc=>"snake_case, plural name for the resource type"}, {:name=>"external_id", :type=>[:null, "string"], :default=>nil}]}], :default=>nil}, {:name=>"broken", :type=>[:null, "boolean"], :default=>nil}]}}}]}}}]}], :default=>nil}]}
10
+
11
+ #Oj.dump(h)
12
+ puts JSON.pretty_generate(h)
13
+ #puts JSON.fast_generate(h)
14
+ #puts JSON.generate(h)
15
+
data/test/foo.rb CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $: << File.dirname(__FILE__)
4
- $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
5
- %w(lib ext).each do |dir|
6
- $: << File.join($oj_dir, dir)
7
- end
3
+ $: << '.'
4
+ $: << '../lib'
5
+ $: << '../ext'
8
6
 
9
7
  require 'oj'
10
8
 
@@ -23,7 +23,7 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
23
23
  'h' => 1000.0,
24
24
  'i' => 0.001
25
25
  }
26
- # Tired of chasing floating point rounding and precision. Oj not uses the
26
+ # Tired of chasing floating point rounding and precision. Oj now uses the
27
27
  # Ruby float parser in compat mode yet on i386 machines there are issues
28
28
  # with this test when the float is included.
29
29
  #@json = '{"a":2,"b":5.23683071,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
@@ -113,7 +113,7 @@ EOT
113
113
  end
114
114
 
115
115
  # TBD Implement JSON.state to return state class.
116
- # set state attibutes from defaults
116
+ # set state attributes from defaults
117
117
  # implement methods
118
118
  # circular should use circular in defaults or maybe always set to true, allow changes with [:check_circular]=
119
119
  def test_states
data/test/mem.rb ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'oj'
9
+
10
+ Oj.default_options = { mode: :rails, cache_keys: false, cache_str: -1 }
11
+
12
+ def mem
13
+ `ps -o rss= -p #{$$}`.to_i
14
+ end
15
+
16
+ ('a'..'z').each { |a|
17
+ ('a'..'z').each { |b|
18
+ ('a'..'z').each { |c|
19
+ ('a'..'z').each { |d|
20
+ ('a'..'z').each { |e|
21
+ ('a'..'z').each { |f|
22
+ key = "#{a}#{b}#{c}#{d}#{e}#{f}"
23
+ x = Oj.load(%|{ "#{key}": 101}|)
24
+ #Oj.dump(x)
25
+ }
26
+ }
27
+ }
28
+ }
29
+ puts "#{a}#{b} #{mem}"
30
+ }
31
+ }
32
+
33
+ Oj::Parser.new(:usual)
data/test/perf_once.rb ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'oj'
9
+
10
+ filename = 'tmp.json'
11
+ File.open(filename, "w") { |f|
12
+ cnt = 0
13
+ f.puts('{')
14
+ ('a'..'z').each { |a|
15
+ ('a'..'z').each { |b|
16
+ ('a'..'z').each { |c|
17
+ ('a'..'z').each { |d|
18
+ f.puts(%|"#{a}#{b}#{c}#{d}":#{cnt},|)
19
+ cnt += 1
20
+ }
21
+ }
22
+ }
23
+ }
24
+ f.puts('"_last":0}')
25
+ }
26
+
27
+ def mem
28
+ `ps -o rss= -p #{$$}`.to_i
29
+ end
30
+
31
+ Oj.default_options = { mode: :strict, cache_keys: false, cache_str: -1 }
32
+ start = Time.now
33
+ Oj.load_file('tmp.json')
34
+ dur = Time.now - start
35
+ GC.start
36
+ puts "no cache duration: #{dur} @ #{mem}"
37
+
38
+ Oj.default_options = { cache_keys: true }
39
+ start = Time.now
40
+ Oj.load_file('tmp.json')
41
+ dur = Time.now - start
42
+ GC.start
43
+ puts "initial cache duration: #{dur} @ #{mem}"
44
+
45
+ start = Time.now
46
+ Oj.load_file('tmp.json')
47
+ dur = Time.now - start
48
+ GC.start
49
+ puts "second cache duration: #{dur} @ #{mem}"
50
+
51
+ 10.times{ GC.start }
52
+ start = Time.now
53
+ Oj.load_file('tmp.json')
54
+ dur = Time.now - start
55
+ GC.start
56
+ puts "after several GCs cache duration: #{dur} @ #{mem}"
57
+
58
+ # TBD check memory use
data/test/perf_parser.rb CHANGED
@@ -53,7 +53,7 @@ Oj.default_options = {create_id: '^', create_additions: true, class_cache: true}
53
53
  if $cache_keys
54
54
  Oj.default_options = {cache_keys: true, cache_str: 6, symbol_keys: $symbol_keys}
55
55
  else
56
- Oj.default_options = {cache_keys: false, cache_str: 0, symbol_keys: $symbol_keys}
56
+ Oj.default_options = {cache_keys: false, cache_str: -1, symbol_keys: $symbol_keys}
57
57
  end
58
58
  JSON.parser = JSON::Ext::Parser
59
59
 
@@ -164,6 +164,11 @@ $obj_json = %|{
164
164
  "juliet": "junk"
165
165
  }|
166
166
 
167
+
168
+ p_usual = Oj::Parser.new(:usual)
169
+ p_usual.cache_keys = $cache_keys
170
+ p_usual.cache_strings = ($cache_keys ? 6 : 0)
171
+ p_usual.symbol_keys = $symbol_keys
167
172
  p_usual.create_id = '^'
168
173
  p_usual.class_cache = true
169
174
  p_usual.ignore_json_create = true
data/test/test_hash.rb CHANGED
@@ -5,7 +5,7 @@ $: << File.dirname(__FILE__)
5
5
 
6
6
  require 'helper'
7
7
 
8
- class Hashi < Minitest::Test
8
+ class HashTest < Minitest::Test
9
9
 
10
10
  module TestModule
11
11
  end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ %w(lib ext test).each do |dir|
5
+ $LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
6
+ end
7
+
8
+ require 'oj'
9
+
10
+ json =<<-EOF
11
+ {
12
+ "$id": "https://example.com/person.schema.json",
13
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
14
+ "title": "Person",
15
+ "type": "object",
16
+ "properties": {
17
+ "firstName": {
18
+ "type": "string",
19
+ "description": "The person's first name."
20
+ },
21
+ "lastName": {
22
+ "type": "string",
23
+ "description": "The person's last name."
24
+ },
25
+ "age": {
26
+ "description": "Age in years which must be equal to or greater than zero.",
27
+ "type": "integer",
28
+ "minimum": 0
29
+ }
30
+ }
31
+ }
32
+ EOF
33
+
34
+ #json = '{"abc": true}'
35
+ #json = '[true,false]'
36
+
37
+ 100_001.times do |i|
38
+ p = Oj::Parser.new(:usual).parse(json)
39
+
40
+ if i % 10_000 == 0
41
+ GC.start
42
+ rss = Integer(`ps -o rss= -p #{Process.pid}`) / 1024.0
43
+ puts "#{i},#{rss} MB"
44
+ end
45
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.0
4
+ version: 3.13.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-08 00:00:00.000000000 Z
11
+ date: 2021-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -91,6 +91,7 @@ extra_rdoc_files:
91
91
  - pages/Security.md
92
92
  - pages/WAB.md
93
93
  files:
94
+ - CHANGELOG.md
94
95
  - LICENSE
95
96
  - README.md
96
97
  - ext/oj/buf.h
@@ -116,7 +117,6 @@ files:
116
117
  - ext/oj/err.h
117
118
  - ext/oj/extconf.rb
118
119
  - ext/oj/fast.c
119
- - ext/oj/hash_test.c
120
120
  - ext/oj/intern.c
121
121
  - ext/oj/intern.h
122
122
  - ext/oj/mimic_json.c
@@ -195,8 +195,8 @@ files:
195
195
  - test/activesupport6/test_common.rb
196
196
  - test/activesupport6/test_helper.rb
197
197
  - test/activesupport6/time_zone_test_helpers.rb
198
- - test/bar.rb
199
- - test/baz.rb
198
+ - test/benny.rb
199
+ - test/big.rb
200
200
  - test/files.rb
201
201
  - test/foo.rb
202
202
  - test/helper.rb
@@ -219,18 +219,19 @@ files:
219
219
  - test/json_gem/json_parser_test.rb
220
220
  - test/json_gem/json_string_matching_test.rb
221
221
  - test/json_gem/test_helper.rb
222
+ - test/mem.rb
222
223
  - test/perf.rb
223
224
  - test/perf_compat.rb
224
225
  - test/perf_fast.rb
225
226
  - test/perf_file.rb
226
227
  - test/perf_object.rb
228
+ - test/perf_once.rb
227
229
  - test/perf_parser.rb
228
230
  - test/perf_saj.rb
229
231
  - test/perf_scp.rb
230
232
  - test/perf_simple.rb
231
233
  - test/perf_strict.rb
232
234
  - test/perf_wab.rb
233
- - test/prec.rb
234
235
  - test/sample.rb
235
236
  - test/sample/change.rb
236
237
  - test/sample/dir.rb
@@ -257,6 +258,7 @@ files:
257
258
  - test/test_null.rb
258
259
  - test/test_object.rb
259
260
  - test/test_parser.rb
261
+ - test/test_parser_memory.rb
260
262
  - test/test_parser_saj.rb
261
263
  - test/test_parser_usual.rb
262
264
  - test/test_rails.rb
@@ -269,7 +271,6 @@ files:
269
271
  - test/tests.rb
270
272
  - test/tests_mimic.rb
271
273
  - test/tests_mimic_addition.rb
272
- - test/zoo.rb
273
274
  homepage: http://www.ohler.com/oj
274
275
  licenses:
275
276
  - MIT
@@ -280,7 +281,7 @@ metadata:
280
281
  homepage_uri: http://www.ohler.com/oj/
281
282
  source_code_uri: https://github.com/ohler55/oj
282
283
  wiki_uri: https://github.com/ohler55/oj/wiki
283
- post_install_message:
284
+ post_install_message:
284
285
  rdoc_options:
285
286
  - "--title"
286
287
  - Oj
@@ -300,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
300
301
  version: '0'
301
302
  requirements: []
302
303
  rubygems_version: 3.2.22
303
- signing_key:
304
+ signing_key:
304
305
  specification_version: 4
305
306
  summary: A fast JSON parser and serializer.
306
307
  test_files:
@@ -324,8 +325,8 @@ test_files:
324
325
  - test/activesupport6/test_common.rb
325
326
  - test/activesupport6/test_helper.rb
326
327
  - test/activesupport6/time_zone_test_helpers.rb
327
- - test/bar.rb
328
- - test/baz.rb
328
+ - test/benny.rb
329
+ - test/big.rb
329
330
  - test/files.rb
330
331
  - test/foo.rb
331
332
  - test/helper.rb
@@ -348,18 +349,19 @@ test_files:
348
349
  - test/json_gem/json_parser_test.rb
349
350
  - test/json_gem/json_string_matching_test.rb
350
351
  - test/json_gem/test_helper.rb
352
+ - test/mem.rb
351
353
  - test/perf.rb
352
354
  - test/perf_compat.rb
353
355
  - test/perf_fast.rb
354
356
  - test/perf_file.rb
355
357
  - test/perf_object.rb
358
+ - test/perf_once.rb
356
359
  - test/perf_parser.rb
357
360
  - test/perf_saj.rb
358
361
  - test/perf_scp.rb
359
362
  - test/perf_simple.rb
360
363
  - test/perf_strict.rb
361
364
  - test/perf_wab.rb
362
- - test/prec.rb
363
365
  - test/sample/change.rb
364
366
  - test/sample/dir.rb
365
367
  - test/sample/doc.rb
@@ -386,6 +388,7 @@ test_files:
386
388
  - test/test_null.rb
387
389
  - test/test_object.rb
388
390
  - test/test_parser.rb
391
+ - test/test_parser_memory.rb
389
392
  - test/test_parser_saj.rb
390
393
  - test/test_parser_usual.rb
391
394
  - test/test_rails.rb
@@ -398,4 +401,3 @@ test_files:
398
401
  - test/tests.rb
399
402
  - test/tests_mimic.rb
400
403
  - test/tests_mimic_addition.rb
401
- - test/zoo.rb