oj 1.2.11 → 1.2.12

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.

data/README.md CHANGED
@@ -4,12 +4,20 @@ A fast JSON parser and Object marshaller as a Ruby gem.
4
4
  ## <a name="installation">Installation</a>
5
5
  gem install oj
6
6
 
7
+ ## <a name="documentation">Documentation</a>
8
+
9
+ *Documentation*: http://www.ohler.com/oj
10
+
7
11
  ## <a name="source">Source</a>
8
12
 
9
13
  *GitHub* *repo*: https://github.com/ohler55/oj
10
14
 
11
15
  *RubyGems* *repo*: https://rubygems.org/gems/oj
12
16
 
17
+ ## <a name="follow">Follow @oxgem on Twitter</a>
18
+
19
+ [Follow @peterohler on Twitter](http://twitter.com/#!/peterohler) for announcements and news about the Oj gem.
20
+
13
21
  ## <a name="build_status">Build Status</a>
14
22
 
15
23
  [![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
@@ -24,21 +32,11 @@ A fast JSON parser and Object marshaller as a Ruby gem.
24
32
 
25
33
  ## <a name="release">Release Notes</a>
26
34
 
27
- ### Release 1.2.11
28
-
29
- - Added :max_stack option to limit the size of string allocated on the stack.
30
-
31
- ### Release 1.2.10
32
-
33
- - Added check for circular on loading of circular dumped JSON.
34
-
35
- - Added support for direct serialization of BigDecimal, Rational, Date, and DateTime.
36
-
37
- - Added json.rb to $" in mimic mode to avoid pulling in the real JSON by accident.
35
+ ### Release 1.2.12
38
36
 
39
- - Oj is now thread safe for all functions.
37
+ - Fixed GC bug in Oj::Doc, the fast parser.
40
38
 
41
- - The / (solidus) character is now placed in strings without being escaped.
39
+ - Serialization of Exceptions in Ruby 1.8.7 now includes message and backtrace.
42
40
 
43
41
  ## <a name="description">Description</a>
44
42
 
@@ -1146,6 +1146,39 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
1146
1146
  }
1147
1147
  #else
1148
1148
  size = d2 * out->indent + 1;
1149
+ #if HAS_EXCEPTION_MAGIC
1150
+ if (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) {
1151
+ if (',' != *(out->cur - 1)) {
1152
+ *out->cur++ = ',';
1153
+ }
1154
+ // message
1155
+ if (out->end - out->cur <= (long)size) {
1156
+ grow(out, size);
1157
+ }
1158
+ fill_indent(out, d2);
1159
+ dump_cstr("~mesg", 5, 0, 0, out);
1160
+ *out->cur++ = ':';
1161
+ dump_val(rb_funcall2(obj, rb_intern("message"), 0, 0), d2, out);
1162
+ if (out->end - out->cur <= 2) {
1163
+ grow(out, 2);
1164
+ }
1165
+ *out->cur++ = ',';
1166
+ // backtrace
1167
+ if (out->end - out->cur <= (long)size) {
1168
+ grow(out, size);
1169
+ }
1170
+ fill_indent(out, d2);
1171
+ dump_cstr("~bt", 3, 0, 0, out);
1172
+ *out->cur++ = ':';
1173
+ dump_val(rb_funcall2(obj, rb_intern("backtrace"), 0, 0), d2, out);
1174
+ if (out->end - out->cur <= 2) {
1175
+ grow(out, 2);
1176
+ }
1177
+ if (0 < cnt) {
1178
+ *out->cur++ = ',';
1179
+ }
1180
+ }
1181
+ #endif
1149
1182
  for (i = cnt; 0 < i; i--, np++) {
1150
1183
  if (out->end - out->cur <= (long)size) {
1151
1184
  grow(out, size);
@@ -22,6 +22,7 @@ dflags = {
22
22
  'HAS_NANO_TIME' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
23
23
  'HAS_RSTRUCT' => ('ruby' == type || 'ree' == type) ? 1 : 0,
24
24
  'HAS_IVAR_HELPERS' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
25
+ 'HAS_EXCEPTION_MAGIC' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 0 : 1,
25
26
  'HAS_PROC_WITH_BLOCK' => ('ruby' == type && ('1' == version[0] && '9' == version[1]) || '2' <= version[0]) ? 1 : 0,
26
27
  'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
27
28
  'SAFE_CACHE' => nil,
@@ -562,7 +562,7 @@ read_obj(ParseInfo pi) {
562
562
  } else if (',' == *pi->s) {
563
563
  pi->s++;
564
564
  } else {
565
- printf("*** '%s'\n", pi->s);
565
+ //printf("*** '%s'\n", pi->s);
566
566
  raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
567
567
  }
568
568
  *end = '\0';
@@ -839,10 +839,12 @@ parse_json(VALUE clas, char *json, int given, int allocated) {
839
839
  pi.doc = doc;
840
840
  // last arg is free func void* func(void*)
841
841
  doc->self = rb_data_object_alloc(clas, doc, 0, free_doc_cb);
842
+ rb_gc_register_address(&doc->self);
842
843
  doc->json = json;
843
844
  DATA_PTR(doc->self) = doc;
844
845
  result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
845
846
  if (given || 0 != ex) {
847
+ rb_gc_unregister_address(&doc->self);
846
848
  DATA_PTR(doc->self) = 0;
847
849
  doc_free(pi.doc);
848
850
  if (allocated) {
@@ -1318,11 +1320,12 @@ doc_type(int argc, VALUE *argv, VALUE self) {
1318
1320
  */
1319
1321
  static VALUE
1320
1322
  doc_fetch(int argc, VALUE *argv, VALUE self) {
1321
- Doc doc = self_doc(self);
1323
+ Doc doc;
1322
1324
  Leaf leaf;
1323
1325
  VALUE val = Qnil;
1324
1326
  const char *path = 0;
1325
1327
 
1328
+ doc = self_doc(self);
1326
1329
  if (1 <= argc) {
1327
1330
  Check_Type(*argv, T_STRING);
1328
1331
  path = StringValuePtr(*argv);
@@ -1584,6 +1587,7 @@ static VALUE
1584
1587
  doc_close(VALUE self) {
1585
1588
  Doc doc = self_doc(self);
1586
1589
 
1590
+ rb_gc_unregister_address(&doc->self);
1587
1591
  DATA_PTR(doc->self) = 0;
1588
1592
  if (0 != doc) {
1589
1593
  xfree(doc->json);
@@ -510,7 +510,22 @@ read_obj(ParseInfo pi) {
510
510
  #ifdef SAFE_CACHE
511
511
  pthread_mutex_unlock(&oj_cache_mutex);
512
512
  #endif
513
+ #if HAS_EXCEPTION_MAGIC
514
+ if ('~' == *ks && Qtrue == rb_obj_is_kind_of(obj, rb_eException)) {
515
+ if (0 == strcmp("~mesg", ks)) {
516
+ VALUE args[1];
517
+
518
+ args[0] = val;
519
+ obj = rb_class_new_instance(1, args, rb_class_of(obj));
520
+ } else if (0 == strcmp("~bt", ks)) {
521
+ rb_funcall(obj, rb_intern("set_backtrace"), 1, val);
522
+ }
523
+ } else {
524
+ rb_ivar_set(obj, var_id, val);
525
+ }
526
+ #else
513
527
  rb_ivar_set(obj, var_id, val);
528
+ #endif
514
529
  } else if (T_HASH == obj_type) {
515
530
  if (Yes == pi->options->sym_key) {
516
531
  rb_hash_aset(obj, rb_str_intern(key), val);
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '1.2.11'
4
+ VERSION = '1.2.12'
5
5
  end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby -wW1
2
+ # encoding: UTF-8
3
+
4
+ $: << File.join(File.dirname(__FILE__), "../lib")
5
+ $: << File.join(File.dirname(__FILE__), "../ext")
6
+
7
+ require 'yajl'
8
+ require 'oj'
9
+
10
+ iter = 100
11
+ s = File.read("boo.json")
12
+ start = Time.now
13
+ iter.times do
14
+ Oj.load(s)
15
+ end
16
+ oj_dt = Time.now - start
17
+ puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/second" % [iter, oj_dt, iter/oj_dt]
18
+
19
+ start = Time.now
20
+ iter.times do
21
+ Yajl::Parser.parse(s)
22
+ end
23
+ yajl_dt = Time.now - start
24
+ puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parsed/second" % [iter, yajl_dt, iter/yajl_dt]
25
+
26
+ puts "Oj is %0.1f times faster than YAJL" % [yajl_dt / oj_dt]
@@ -0,0 +1,18 @@
1
+
2
+ $: << File.join(File.dirname(__FILE__), "../lib")
3
+ $: << File.join(File.dirname(__FILE__), "../ext")
4
+
5
+ require 'oj'
6
+ require 'bigdecimal'
7
+
8
+ stuff = [
9
+ BigDecimal.new('10'),
10
+ Date.today,
11
+ Time.now,
12
+ DateTime.now
13
+ ]
14
+
15
+ puts Oj.dump(stuff, :mode => :strict)
16
+ puts Oj.dump(stuff, :mode => :compat)
17
+ puts Oj.dump(stuff, :mode => :object)
18
+
@@ -15,19 +15,6 @@ opts = OptionParser.new
15
15
  opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
16
16
  files = opts.parse(ARGV)
17
17
 
18
- class Foo
19
- def initialize()
20
- @x = true
21
- @y = 58
22
- end
23
- def to_json()
24
- %{{"x":#{@x},"y":#{@y}}}
25
- end
26
- def to_hash()
27
- { 'x' => @x, 'y' => @y }
28
- end
29
- end
30
-
31
18
  iter = 100000
32
19
  s = %{
33
20
  { "class": "Foo::Bar",
@@ -36,41 +23,36 @@ s = %{
36
23
  }
37
24
  }
38
25
 
39
- obj = Oj.load(s)
40
- obj["foo"] = Foo.new()
41
-
42
- Oj.default_options = { :indent => 0, :effort => :internal }
43
-
44
- puts
45
-
46
26
  start = Time.now
47
27
  iter.times do
48
28
  Oj.load(s)
49
29
  end
50
- dt = Time.now - start
51
- puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
30
+ oj_dt = Time.now - start
31
+ puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, oj_dt, iter/oj_dt/1000.0]
52
32
 
53
33
  start = Time.now
54
34
  iter.times do
55
35
  Yajl::Parser.parse(s)
56
36
  end
57
- dt = Time.now - start
58
- puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parses/msec" % [iter, dt, iter/dt/1000.0]
37
+ yajl_dt = Time.now - start
38
+ puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parses/msec" % [iter, yajl_dt, iter/yajl_dt/1000.0]
59
39
 
60
- puts
40
+ puts "Oj is %0.1f times faster than YAJL at parsing." % [yajl_dt / oj_dt]
61
41
 
42
+
43
+ obj = Oj.load(s)
62
44
  start = Time.now
63
45
  iter.times do
64
46
  Oj.dump(obj)
65
47
  end
66
- dt = Time.now - start
67
- puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
48
+ oj_dt = Time.now - start
49
+ puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, oj_dt, iter/oj_dt/1000.0]
68
50
 
69
51
  start = Time.now
70
52
  iter.times do
71
53
  Yajl::Encoder.encode(obj)
72
54
  end
73
- dt = Time.now - start
74
- puts "%d Yajl::Encoder.encode()s in %0.3f seconds or %0.1f encodes/msec" % [iter, dt, iter/dt/1000.0]
55
+ yajl_dt = Time.now - start
56
+ puts "%d Yajl::Encoder.encode()s in %0.3f seconds or %0.1f encodes/msec" % [iter, yajl_dt, iter/yajl_dt/1000.0]
75
57
 
76
- puts
58
+ puts "Oj is %0.1f times faster than YAJL at dumping." % [yajl_dt / oj_dt]
@@ -0,0 +1,140 @@
1
+ require 'cgi'
2
+ require 'oj'
3
+
4
+ AD_MARKUP = CGI.escape("asdf" * 100)
5
+
6
+ SEATBID = '{
7
+ "bid" : [{
8
+ "id": "1",
9
+ "impid" : "102",
10
+ "price": 9.43,
11
+ "adid" : "314",
12
+ "nurl": "http://adserver.com/winnotice?impid=102",
13
+ "adm" : "' + AD_MARKUP + '",
14
+ "adomain" : ["advertiserdomain.com"],
15
+ "iurl" : "http://adserver.com/pathtosampleimage",
16
+ "cid" : "campaign111",
17
+ "crid" : "creative112",
18
+ "attr" : [1,2,3,4,5,6,7,12]
19
+ }],
20
+ "seat" : "512",
21
+ "group" : "128"
22
+ }'
23
+
24
+
25
+ LARGE_JSON = '{
26
+ "id": "1234567890",
27
+ "units" : 0,
28
+ "bidid": "abc1123",
29
+ "cur": "EUR",
30
+ "seatbid": [' + ([SEATBID] * 100).join(', ') + ']
31
+ }'
32
+
33
+
34
+ class Bid
35
+
36
+ attr_accessor :id,
37
+ :bidid,
38
+ :cur,
39
+ :seat,
40
+ :group,
41
+ :impid,
42
+ :price,
43
+ :units,
44
+ :adid,
45
+ :nurl,
46
+ :adm,
47
+ :adomain,
48
+ :iurl,
49
+ :cid,
50
+ :crid,
51
+ :attr,
52
+ :nbr,
53
+ :partner_id
54
+
55
+ alias :currency :cur
56
+ alias :auction_id :id
57
+
58
+ def parsed_adm
59
+ return replace_macros(self.adm)
60
+ end
61
+
62
+ def parsed_nurl
63
+ return replace_macros(self.nurl)
64
+ end
65
+
66
+ def replace_macros(template)
67
+ return nil if !template
68
+ {
69
+ '${AUCTION_ID}' => self.id,
70
+ '${AUCTION_BID_ID}' => self.bidid,
71
+ '${AUCTION_IMP_ID}' => self.impid,
72
+ '${AUCTION_SEAT_ID}' => self.seat,
73
+ '${AUCTION_AD_ID}' => self.adid,
74
+ '${AUCTION_PRICE}' => self.price,
75
+ '${AUCTION_CURRENCY}' => self.cur,
76
+ '${AUCTION_UNITS}' => self.units,
77
+ }.each do |macro, v|
78
+ template = template.gsub(macro, v.to_s)
79
+ end
80
+ template
81
+ end
82
+ end
83
+
84
+ #GC.disable
85
+
86
+ class BidResponseParser
87
+ REQUIRED_ATTRIBUTES = [:id, :impid, :price].freeze
88
+
89
+ def self.parse(json)
90
+ return nil if !json
91
+ extract_fast(json)
92
+ end
93
+
94
+ def self.extract_fast(json)
95
+ doc = Oj::Doc.open(json)
96
+ #Oj::Doc.open(json) do |doc|
97
+ bid = Bid.new
98
+
99
+ # bid-response object
100
+ bid.id = doc.fetch '/id'
101
+
102
+ bid.bidid = doc.fetch '/bidid'
103
+ bid.units = doc.fetch('/units') || 0
104
+ bid.cur = doc.fetch '/cur'
105
+ bid.nbr = doc.fetch('/nbr') || 0 # Mobile RTB 1.0 only
106
+
107
+ # EM: we do not expect more than 1 bid object in the response,
108
+ # as we only send single ads in the bid-request (no multi-ad-auctions) atm.
109
+ # seatbid-obj
110
+ bid.seat = doc.fetch '/seatbid/0/seat'
111
+ bid.group = doc.fetch '/seatbid/0/group'
112
+
113
+ # bid-obj
114
+ bid_path = '/seatbid/0/bid/0'
115
+ bid.impid = doc.fetch "#{bid_path}/impid"
116
+ bid.adid = doc.fetch "#{bid_path}/adid"
117
+ bid.nurl = doc.fetch "#{bid_path}/nurl"
118
+ bid.adm = doc.fetch "#{bid_path}/adm"
119
+ bid.adomain = doc.fetch "#{bid_path}/adomain"
120
+ bid.iurl = doc.fetch "#{bid_path}/iurl"
121
+ bid.cid = doc.fetch "#{bid_path}/cid"
122
+ bid.crid = doc.fetch "#{bid_path}/crid"
123
+ bid.attr = doc.fetch "#{bid_path}/attr"
124
+
125
+ # sadly we need to check this explicitly, because nil.to_f returns 0.0
126
+ if doc.fetch("#{bid_path}/price") == nil
127
+ raise "required attribute price missing"
128
+ end
129
+
130
+ bid.price = doc.fetch("#{bid_path}/price").to_f
131
+
132
+ doc.close # needed when not in Proc to cleanup
133
+ return bid
134
+ #end
135
+ end
136
+ end
137
+
138
+ 1000.times do
139
+ BidResponseParser.parse(LARGE_JSON)
140
+ end
@@ -519,10 +519,14 @@ class Juice < ::Test::Unit::TestCase
519
519
  #puts "*** #{json}"
520
520
  e2 = Oj.load(json, :mode => :strict)
521
521
  assert_equal(err.class.to_s, e2['^o'])
522
- unless RUBY_VERSION.start_with?('1.8') || 'rubinius' == $ruby
523
- assert_equal(err.message, e2['~mesg'])
524
- assert_equal(err.backtrace, e2['~bt'])
525
- e2 = Oj.load(json, :mode => :object)
522
+ assert_equal(err.message, e2['~mesg'])
523
+ assert_equal(err.backtrace, e2['~bt'])
524
+ e2 = Oj.load(json, :mode => :object)
525
+ if RUBY_VERSION.start_with?('1.8') || 'rubinius' == $ruby
526
+ assert_equal(e.class, e2.class);
527
+ assert_equal(e.message, e2.message);
528
+ assert_equal(e.backtrace, e2.backtrace);
529
+ else
526
530
  assert_equal(e, e2);
527
531
  end
528
532
  end
@@ -0,0 +1,54 @@
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 = 1000000
15
+
16
+ opts = OptionParser.new
17
+ opts.on("-v", "verbose") { $verbose = true }
18
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
19
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
20
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
21
+ files = opts.parse(ARGV)
22
+
23
+ $obj = {
24
+ 'a' => 'Alpha', # string
25
+ 'b' => true, # boolean
26
+ 'c' => 12345, # number
27
+ 'd' => [ true, [false, [12345, nil], 3.967, ['something', false], nil]], # mix it up array
28
+ 'e' => { 'one' => 1, 'two' => 2 }, # hash
29
+ 'f' => nil, # nil
30
+ 'g' => 12345678901234567890123456789, # big number
31
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
32
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
33
+ }
34
+
35
+ Oj.default_options = { :indent => $indent, :mode => :strict }
36
+
37
+ $json = Oj.dump($obj)
38
+
39
+ if $verbose
40
+ puts "json:\n#{$json}\n"
41
+ end
42
+
43
+ puts '-' * 80
44
+ puts "Parse Performance"
45
+ Oj::Fast.open($json) do |fast|
46
+ fast.move('/d/2/4/2')
47
+ puts fast.where2?
48
+ puts fast.where?
49
+ perf = Perf.new()
50
+ perf.add('Oj:fast', 'where') { fast.where? }
51
+ perf.add('Oj:fast2', 'where2') { fast.where2? }
52
+ perf.run($iter)
53
+ end
54
+ puts
metadata CHANGED
@@ -1,27 +1,24 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: oj
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.12
4
5
  prerelease:
5
- version: 1.2.11
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Peter Ohler
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2012-06-21 00:00:00 Z
12
+ date: 2012-07-06 00:00:00.000000000 Z
14
13
  dependencies: []
15
-
16
- description: "The fastest JSON parser and object serializer. "
14
+ description: ! 'The fastest JSON parser and object serializer. '
17
15
  email: peter@ohler.com
18
16
  executables: []
19
-
20
- extensions:
17
+ extensions:
21
18
  - ext/oj/extconf.rb
22
- extra_rdoc_files:
19
+ extra_rdoc_files:
23
20
  - README.md
24
- files:
21
+ files:
25
22
  - lib/oj/bag.rb
26
23
  - lib/oj/version.rb
27
24
  - lib/oj.rb
@@ -35,13 +32,14 @@ files:
35
32
  - ext/oj/fast.c
36
33
  - ext/oj/load.c
37
34
  - ext/oj/oj.c
35
+ - test/boo.rb
36
+ - test/bug.rb
38
37
  - test/files.rb
38
+ - test/foo.rb
39
+ - test/oj-test/test.rb
39
40
  - test/perf.rb
40
- - test/perf1.rb
41
- - test/perf2.rb
42
41
  - test/perf_fast.rb
43
42
  - test/perf_obj.rb
44
- - test/perf_obj_old.rb
45
43
  - test/perf_simple.rb
46
44
  - test/perf_strict.rb
47
45
  - test/sample/change.rb
@@ -61,37 +59,35 @@ files:
61
59
  - test/test_fast.rb
62
60
  - test/test_mimic.rb
63
61
  - test/tests.rb
62
+ - test/where.rb
64
63
  - LICENSE
65
64
  - README.md
66
65
  homepage: http://www.ohler.com/oj
67
66
  licenses: []
68
-
69
67
  post_install_message:
70
- rdoc_options:
68
+ rdoc_options:
71
69
  - --main
72
70
  - README.md
73
- require_paths:
71
+ require_paths:
74
72
  - lib
75
73
  - ext
76
- required_ruby_version: !ruby/object:Gem::Requirement
74
+ required_ruby_version: !ruby/object:Gem::Requirement
77
75
  none: false
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: "0"
82
- required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
81
  none: false
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- version: "0"
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
88
86
  requirements: []
89
-
90
87
  rubyforge_project: oj
91
88
  rubygems_version: 1.8.23
92
89
  signing_key:
93
90
  specification_version: 3
94
91
  summary: A fast JSON parser and serializer.
95
92
  test_files: []
96
-
97
93
  has_rdoc: true
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env ruby -wW1
2
- # encoding: UTF-8
3
-
4
- $: << File.join(File.dirname(__FILE__), "../lib")
5
- $: << File.join(File.dirname(__FILE__), "../ext")
6
-
7
- #require 'test/unit'
8
- require 'optparse'
9
- require 'oj'
10
- require 'ox'
11
-
12
- $indent = 2
13
-
14
- opts = OptionParser.new
15
- opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
16
- files = opts.parse(ARGV)
17
-
18
- iter = 100000
19
- s = %{
20
- { "class": "Foo::Bar",
21
- "attr1": [ true, [false, [12345, null], 3.967, ["something", false], null]],
22
- "attr2": { "one": 1 }
23
- }
24
- }
25
- #s = File.read('sample.json')
26
-
27
- Oj.default_options = { :indent => 0 }
28
-
29
- obj = Oj.load(s)
30
- xml = Ox.dump(obj, :indent => 0)
31
-
32
- puts xml
33
-
34
- start = Time.now
35
- iter.times do
36
- Oj.load(s)
37
- end
38
- dt = Time.now - start
39
- puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
40
-
41
- start = Time.now
42
- iter.times do
43
- Ox.load(xml)
44
- end
45
- dt = Time.now - start
46
- puts "%d Ox.load()s in %0.3f seconds or %0.1f loads/msec" % [iter, dt, iter/dt/1000.0]
47
-
48
- puts
49
-
50
- start = Time.now
51
- iter.times do
52
- Oj.dump(obj)
53
- end
54
- dt = Time.now - start
55
- puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
56
-
57
- start = Time.now
58
- iter.times do
59
- Ox.dump(obj)
60
- end
61
- dt = Time.now - start
62
- puts "%d Ox.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter, dt, iter/dt/1000.0]
63
-
64
- puts
@@ -1,213 +0,0 @@
1
- #!/usr/bin/env ruby -wW1
2
-
3
- $: << '.'
4
- $: << '..'
5
- $: << '../lib'
6
- $: << '../ext'
7
-
8
- if __FILE__ == $0
9
- if (i = ARGV.index('-I'))
10
- x,path = ARGV.slice!(i, 2)
11
- $: << path
12
- end
13
- end
14
-
15
- require 'optparse'
16
- require 'ox'
17
- require 'oj'
18
- require 'perf'
19
- require 'sample'
20
- require 'files'
21
-
22
- $verbose = 0
23
- $circular = false
24
- $indent = 0
25
-
26
- do_sample = false
27
- do_files = false
28
-
29
- do_load = false
30
- do_dump = false
31
- do_read = false
32
- do_write = false
33
- $iter = 1000
34
-
35
- opts = OptionParser.new
36
- opts.on("-v", "increase verbosity") { $verbose += 1 }
37
-
38
- opts.on("-c", "circular options") { $circular = true }
39
-
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 }
42
-
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 }
48
-
49
- opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i }
50
-
51
- opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
52
- files = opts.parse(ARGV)
53
-
54
- if files.empty?
55
- data = []
56
- obj = do_sample ? sample_doc(2) : files('..')
57
- mars = Marshal.dump(obj)
58
- xml = Ox.dump(obj, :indent => $indent, circular: $circular)
59
- json = Oj.dump(obj, :indent => $indent, circular: $circular)
60
- File.open('sample.xml', 'w') { |f| f.write(xml) }
61
- File.open('sample.json', 'w') { |f| f.write(json) }
62
- File.open('sample.marshal', 'w') { |f| f.write(mars) }
63
- data << { :file => 'sample.xml', :obj => obj, :xml => xml, :marshal => mars, :json => json }
64
- else
65
- puts "loading and parsing #{files}\n\n"
66
- # TBD change to allow xml and json
67
- data = files.map do |f|
68
- xml = File.read(f)
69
- obj = Ox.load(xml);
70
- mars = Marshal.dump(obj)
71
- json = Oj.dump(obj, :indent => $indent, circular: $circular)
72
- { :file => f, :obj => obj, :xml => xml, :marshal => mars, :json => json }
73
- end
74
- end
75
-
76
- $ox_load_time = 0
77
- $mars_load_time = 0
78
- $ox_dump_time = 0
79
- $oj_dump_time = 0
80
- $mars_dump_time = 0
81
-
82
- def perf_load(d)
83
- filename = d[:file]
84
- marshal_filename = 'sample.marshal'
85
- xml = d[:xml]
86
- mars = d[:marshal]
87
- json = d[:json]
88
-
89
- if 0 < $verbose
90
- obj = Ox.load(xml, :mode => :object, :trace => $verbose)
91
- return
92
- end
93
- start = Time.now
94
- (1..$iter).each do
95
- obj = Ox.load(xml, :mode => :object)
96
- end
97
- $ox_load_time = Time.now - start
98
- puts "Parsing #{$iter} times with Ox took #{$ox_load_time} seconds."
99
-
100
- start = Time.now
101
- (1..$iter).each do
102
- obj = Oj.load(json, :mode => :object)
103
- end
104
- $oj_load_time = Time.now - start
105
- puts "Parsing #{$iter} times with Oj took #{$oj_load_time} seconds."
106
-
107
- start = Time.now
108
- (1..$iter).each do
109
- obj = Marshal.load(mars)
110
- end
111
- $mars_load_time = Time.now - start
112
- puts "Marshalling #{$iter} times took #{$mars_load_time} seconds."
113
- puts ">>> Ox is %0.1f faster than Marshal loading.\n\n" % [$mars_load_time/$ox_load_time]
114
- end
115
-
116
- def perf_dump(d)
117
- obj = d[:obj]
118
-
119
- start = Time.now
120
- (1..$iter).each do
121
- xml = Ox.dump(obj, :indent => $indent, :circular => $circular)
122
- #puts "*** ox:\n#{xml}"
123
- end
124
- $ox_dump_time = Time.now - start
125
- puts "Ox dumping #{$iter} times with ox took #{$ox_dump_time} seconds."
126
-
127
- Oj.default_options = {:indent => $indent}
128
- start = Time.now
129
- (1..$iter).each do
130
- json = Oj.dump(obj)
131
- end
132
- $oj_dump_time = Time.now - start
133
- puts "Oj dumping #{$iter} times with oj took #{$oj_dump_time} seconds."
134
-
135
- obj = d[:obj]
136
- start = Time.now
137
- (1..$iter).each do
138
- m = Marshal.dump(obj)
139
- end
140
- $mars_dump_time = Time.now - start
141
- puts "Marshal dumping #{$iter} times took #{$mars_dump_time} seconds."
142
- puts ">>> Ox is %0.1f faster than Marshal dumping.\n\n" % [$mars_dump_time/$ox_dump_time]
143
- end
144
-
145
- def perf_read(d)
146
- ox_read_time = 0
147
- mars_read_time = 0
148
-
149
- filename = d[:file]
150
- marshal_filename = 'sample.marshal'
151
- xml = d[:xml]
152
- mars = d[:marshal]
153
-
154
- # now load from the file
155
- start = Time.now
156
- (1..$iter).each do
157
- obj = Ox.load_file(filename, :mode => :object)
158
- end
159
- ox_read_time = Time.now - start
160
- puts "Loading and parsing #{$iter} times with ox took #{ox_read_time} seconds."
161
-
162
- start = Time.now
163
- (1..$iter).each do
164
- m = File.read(marshal_filename)
165
- obj = Marshal.load(m)
166
- end
167
- mars_read_time = Time.now - start
168
- puts "Reading and marshalling #{$iter} times took #{mars_read_time} seconds."
169
- puts ">>> Ox is %0.1f faster than Marshal loading and parsing.\n\n" % [mars_read_time/ox_read_time]
170
-
171
- end
172
-
173
- def perf_write(d)
174
- ox_write_time = 0
175
- mars_write_time = 0
176
-
177
- ox_filename = 'out.xml'
178
- marshal_filename = 'out.marshal'
179
- obj = d[:obj]
180
-
181
- start = Time.now
182
- (1..$iter).each do
183
- xml = Ox.to_file(ox_filename, obj, :indent => $indent)
184
- end
185
- ox_write_time = Time.now - start
186
- puts "Ox dumping #{$iter} times with ox took #{ox_write_time} seconds."
187
-
188
- start = Time.now
189
- (1..$iter).each do
190
- m = Marshal.dump(obj, circular: $circular)
191
- File.open(marshal_filename, "w") { |f| f.write(m) }
192
- end
193
- mars_write_time = Time.now - start
194
- puts "Marshal dumping and writing #{$iter} times took #{mars_write_time} seconds."
195
- puts ">>> Ox is %0.1f faster than Marshal dumping.\n\n" % [mars_write_time/ox_write_time]
196
-
197
- end
198
-
199
- #if do_sample or do_files
200
- data.each do |d|
201
- puts "Using file #{d[:file]}."
202
-
203
- perf_load(d) if do_load
204
- perf_dump(d) if do_dump
205
- if do_load and do_dump
206
- puts ">>> Ox is %0.1f faster than Marshal dumping and loading.\n\n" % [($mars_load_time + $mars_dump_time)/($ox_load_time + $ox_dump_time)] unless 0 == $mars_load_time
207
- end
208
-
209
- perf_read(d) if do_read
210
- perf_write(d) if do_write
211
-
212
- end
213
- #end