oj 0.5.2 → 0.6.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.
- data/README.md +115 -6
- data/ext/oj/dump.c +252 -9
- data/ext/oj/load.c +26 -1
- data/ext/oj/oj.c +57 -75
- data/ext/oj/oj.h +16 -15
- data/lib/oj/version.rb +1 -1
- data/test/perf_simple.rb +246 -24
- data/test/sample.rb +37 -0
- data/test/simple.rb +112 -8
- metadata +3 -2
data/ext/oj/load.c
CHANGED
@@ -106,7 +106,7 @@ next_white(ParseInfo pi) {
|
|
106
106
|
}
|
107
107
|
|
108
108
|
VALUE
|
109
|
-
|
109
|
+
oj_parse(char *json, Options options) {
|
110
110
|
VALUE obj;
|
111
111
|
struct _ParseInfo pi;
|
112
112
|
|
@@ -116,7 +116,11 @@ parse(char *json, Options options) {
|
|
116
116
|
/* initialize parse info */
|
117
117
|
pi.str = json;
|
118
118
|
pi.s = json;
|
119
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
119
120
|
pi.encoding = ('\0' == *options->encoding) ? 0 : rb_enc_find(options->encoding);
|
121
|
+
#else
|
122
|
+
pi.encoding = 0;
|
123
|
+
#endif
|
120
124
|
pi.options = options;
|
121
125
|
if (Qundef == (obj = read_next(&pi))) {
|
122
126
|
raise_error("no object read", pi.str, pi.s);
|
@@ -261,14 +265,22 @@ read_str(ParseInfo pi) {
|
|
261
265
|
return s;
|
262
266
|
}
|
263
267
|
|
268
|
+
#ifdef RUBINIUS
|
269
|
+
#define NUM_MAX 0x07FFFFFF
|
270
|
+
#else
|
271
|
+
#define NUM_MAX (FIXNUM_MAX >> 8)
|
272
|
+
#endif
|
273
|
+
|
264
274
|
static VALUE
|
265
275
|
read_num(ParseInfo pi) {
|
276
|
+
char *start = pi->s;
|
266
277
|
int64_t n = 0;
|
267
278
|
long a = 0;
|
268
279
|
long div = 1;
|
269
280
|
long e = 0;
|
270
281
|
int neg = 0;
|
271
282
|
int eneg = 0;
|
283
|
+
int big = 0;
|
272
284
|
|
273
285
|
if ('-' == *pi->s) {
|
274
286
|
pi->s++;
|
@@ -278,6 +290,19 @@ read_num(ParseInfo pi) {
|
|
278
290
|
}
|
279
291
|
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
280
292
|
n = n * 10 + (*pi->s - '0');
|
293
|
+
if (NUM_MAX <= n) {
|
294
|
+
big = 1;
|
295
|
+
}
|
296
|
+
}
|
297
|
+
if (big) {
|
298
|
+
char c = *pi->s;
|
299
|
+
VALUE num;
|
300
|
+
|
301
|
+
*pi->s = '\0';
|
302
|
+
num = rb_cstr_to_inum(start, 10, 0);
|
303
|
+
*pi->s = c;
|
304
|
+
|
305
|
+
return num;
|
281
306
|
}
|
282
307
|
if ('.' == *pi->s) {
|
283
308
|
pi->s++;
|
data/ext/oj/oj.c
CHANGED
@@ -45,23 +45,26 @@ void Init_oj();
|
|
45
45
|
|
46
46
|
VALUE Oj = Qnil;
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
VALUE
|
55
|
-
VALUE
|
56
|
-
VALUE
|
57
|
-
VALUE
|
48
|
+
ID oj_instance_variables_id;
|
49
|
+
ID oj_to_hash_id;
|
50
|
+
ID oj_to_json_id;
|
51
|
+
ID oj_tv_sec_id;
|
52
|
+
ID oj_tv_usec_id;
|
53
|
+
|
54
|
+
static VALUE circular_sym;
|
55
|
+
static VALUE compat_sym;
|
56
|
+
static VALUE encoding_sym;
|
57
|
+
static VALUE indent_sym;
|
58
|
+
static VALUE mode_sym;
|
59
|
+
static VALUE null_sym;
|
60
|
+
static VALUE object_sym;
|
61
|
+
static VALUE strict_sym;
|
58
62
|
|
59
63
|
static struct _Options default_options = {
|
60
64
|
{ '\0' }, // encoding
|
61
65
|
0, // indent
|
62
66
|
No, // circular
|
63
|
-
|
64
|
-
TolerantEffort, // effort
|
67
|
+
ObjectMode, // mode
|
65
68
|
};
|
66
69
|
|
67
70
|
/* call-seq: default_options() => Hash
|
@@ -70,8 +73,7 @@ static struct _Options default_options = {
|
|
70
73
|
* - indent: [Fixnum] number of spaces to indent each element in an XML document
|
71
74
|
* - encoding: [String] character encoding for the JSON file
|
72
75
|
* - circular: [true|false|nil] support circular references while dumping
|
73
|
-
* - mode: [:object|:
|
74
|
-
* - effort: [:strict|:tolerant|:lazy_define] set the tolerance level for loading
|
76
|
+
* - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
|
75
77
|
* @return [Hash] all current option settings.
|
76
78
|
*/
|
77
79
|
static VALUE
|
@@ -83,17 +85,11 @@ get_def_opts(VALUE self) {
|
|
83
85
|
rb_hash_aset(opts, indent_sym, INT2FIX(default_options.indent));
|
84
86
|
rb_hash_aset(opts, circular_sym, (Yes == default_options.circular) ? Qtrue : ((No == default_options.circular) ? Qfalse : Qnil));
|
85
87
|
switch (default_options.mode) {
|
86
|
-
case
|
87
|
-
case
|
88
|
-
case
|
89
|
-
|
90
|
-
|
91
|
-
switch (default_options.effort) {
|
92
|
-
case StrictEffort: rb_hash_aset(opts, effort_sym, strict_sym); break;
|
93
|
-
case TolerantEffort: rb_hash_aset(opts, effort_sym, tolerant_sym); break;
|
94
|
-
case LazyEffort: rb_hash_aset(opts, effort_sym, lazy_sym); break;
|
95
|
-
case NoEffort:
|
96
|
-
default: rb_hash_aset(opts, effort_sym, Qnil); break;
|
88
|
+
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
89
|
+
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
90
|
+
case NullMode: rb_hash_aset(opts, mode_sym, null_sym); break;
|
91
|
+
case ObjectMode:
|
92
|
+
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
97
93
|
}
|
98
94
|
return opts;
|
99
95
|
}
|
@@ -105,14 +101,14 @@ get_def_opts(VALUE self) {
|
|
105
101
|
* @param [Fixnum] :indent number of spaces to indent each element in an XML document
|
106
102
|
* @param [String] :encoding character encoding for the JSON file
|
107
103
|
* @param [true|false|nil] :circular support circular references while dumping
|
108
|
-
* @
|
109
|
-
*
|
110
|
-
*
|
111
|
-
*
|
112
|
-
*
|
113
|
-
*
|
114
|
-
* null
|
115
|
-
* @return [nil]
|
104
|
+
* @parsm [:object|:strict|:compat|:null] load and dump mode to use for JSON
|
105
|
+
* :strict raises an exception when a non-supported Object is
|
106
|
+
* encountered. :compat attempts to extract variable values from an
|
107
|
+
* Object using to_json() or to_hash() then it walks the Object's
|
108
|
+
* variables if neither is found. The :object mode ignores to_hash()
|
109
|
+
* and to_json() methods and encodes variables using code internal to
|
110
|
+
* the Oj gem. The :null mode ignores non-supported Objects and
|
111
|
+
* replaces them with a null. @return [nil]
|
116
112
|
*/
|
117
113
|
static VALUE
|
118
114
|
set_def_opts(VALUE self, VALUE opts) {
|
@@ -142,32 +138,20 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
142
138
|
}
|
143
139
|
|
144
140
|
v = rb_hash_lookup2(opts, mode_sym, Qundef);
|
145
|
-
if (Qundef == v) {
|
146
|
-
//
|
147
|
-
} else if (Qnil == v) {
|
148
|
-
default_options.mode = NoMode;
|
141
|
+
if (Qundef == v || Qnil == v) {
|
142
|
+
// ignore
|
149
143
|
} else if (object_sym == v) {
|
150
144
|
default_options.mode = ObjectMode;
|
151
|
-
} else if (simple_sym == v) {
|
152
|
-
default_options.mode = SimpleMode;
|
153
|
-
} else {
|
154
|
-
rb_raise(rb_eArgError, ":mode must be :object, :simple, or nil.\n");
|
155
|
-
}
|
156
|
-
|
157
|
-
v = rb_hash_lookup2(opts, effort_sym, Qundef);
|
158
|
-
if (Qundef == v) {
|
159
|
-
// no change
|
160
|
-
} else if (Qnil == v) {
|
161
|
-
default_options.effort = NoEffort;
|
162
145
|
} else if (strict_sym == v) {
|
163
|
-
default_options.
|
164
|
-
} else if (
|
165
|
-
default_options.
|
166
|
-
} else if (
|
167
|
-
default_options.
|
146
|
+
default_options.mode = StrictMode;
|
147
|
+
} else if (compat_sym == v) {
|
148
|
+
default_options.mode = CompatMode;
|
149
|
+
} else if (null_sym == v) {
|
150
|
+
default_options.mode = NullMode;
|
168
151
|
} else {
|
169
|
-
rb_raise(rb_eArgError, ":
|
152
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.\n");
|
170
153
|
}
|
154
|
+
|
171
155
|
for (o = ynos; 0 != o->attr; o++) {
|
172
156
|
v = rb_hash_lookup2(opts, o->sym, Qundef);
|
173
157
|
if (Qundef == v) {
|
@@ -211,21 +195,14 @@ parse_options(VALUE ropts, Options copts) {
|
|
211
195
|
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
212
196
|
if (object_sym == v) {
|
213
197
|
copts->mode = ObjectMode;
|
214
|
-
} else if (simple_sym == v) {
|
215
|
-
copts->mode = SimpleMode;
|
216
|
-
} else {
|
217
|
-
rb_raise(rb_eArgError, ":mode must be :object or :simple.\n");
|
218
|
-
}
|
219
|
-
}
|
220
|
-
if (Qnil != (v = rb_hash_lookup(ropts, effort_sym))) {
|
221
|
-
if (lazy_sym == v) {
|
222
|
-
copts->effort = LazyEffort;
|
223
|
-
} else if (tolerant_sym == v) {
|
224
|
-
copts->effort = TolerantEffort;
|
225
198
|
} else if (strict_sym == v) {
|
226
|
-
copts->
|
199
|
+
copts->mode = StrictMode;
|
200
|
+
} else if (compat_sym == v) {
|
201
|
+
copts->mode = CompatMode;
|
202
|
+
} else if (null_sym == v) {
|
203
|
+
copts->mode = NullMode;
|
227
204
|
} else {
|
228
|
-
rb_raise(rb_eArgError, ":
|
205
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.\n");
|
229
206
|
}
|
230
207
|
}
|
231
208
|
for (o = ynos; 0 != o->attr; o++) {
|
@@ -252,7 +229,7 @@ load(char *json, int argc, VALUE *argv, VALUE self) {
|
|
252
229
|
if (1 == argc) {
|
253
230
|
parse_options(*argv, &options);
|
254
231
|
}
|
255
|
-
obj =
|
232
|
+
obj = oj_parse(json, &options);
|
256
233
|
free(json);
|
257
234
|
|
258
235
|
return obj;
|
@@ -321,7 +298,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
321
298
|
if (2 == argc) {
|
322
299
|
parse_options(argv[1], &copts);
|
323
300
|
}
|
324
|
-
if (0 == (json =
|
301
|
+
if (0 == (json = oj_write_obj_to_str(*argv, &copts))) {
|
325
302
|
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
326
303
|
}
|
327
304
|
rstr = rb_str_new2(json);
|
@@ -348,21 +325,26 @@ void Init_oj() {
|
|
348
325
|
rb_define_module_function(Oj, "load_file", load_file, -1);
|
349
326
|
rb_define_module_function(Oj, "dump", dump, -1);
|
350
327
|
|
328
|
+
oj_instance_variables_id = rb_intern("instance_variables");
|
329
|
+
oj_to_hash_id = rb_intern("to_hash");
|
330
|
+
oj_to_json_id = rb_intern("to_json");
|
331
|
+
oj_tv_sec_id = rb_intern("tv_sec");
|
332
|
+
oj_tv_usec_id = rb_intern("tv_usec");
|
333
|
+
|
351
334
|
circular_sym = ID2SYM(rb_intern("circular")); rb_ary_push(keep, circular_sym);
|
352
|
-
|
335
|
+
compat_sym = ID2SYM(rb_intern("compat")); rb_ary_push(keep, compat_sym);
|
353
336
|
encoding_sym = ID2SYM(rb_intern("encoding")); rb_ary_push(keep, encoding_sym);
|
354
337
|
indent_sym = ID2SYM(rb_intern("indent")); rb_ary_push(keep, indent_sym);
|
355
|
-
lazy_sym = ID2SYM(rb_intern("lazy")); rb_ary_push(keep, lazy_sym);
|
356
338
|
mode_sym = ID2SYM(rb_intern("mode")); rb_ary_push(keep, mode_sym);
|
339
|
+
null_sym = ID2SYM(rb_intern("null")); rb_ary_push(keep, null_sym);
|
357
340
|
object_sym = ID2SYM(rb_intern("object")); rb_ary_push(keep, object_sym);
|
358
|
-
simple_sym = ID2SYM(rb_intern("simple")); rb_ary_push(keep, simple_sym);
|
359
341
|
strict_sym = ID2SYM(rb_intern("strict")); rb_ary_push(keep, strict_sym);
|
360
|
-
|
361
|
-
default_options.
|
342
|
+
|
343
|
+
default_options.mode = ObjectMode;
|
362
344
|
}
|
363
345
|
|
364
346
|
void
|
365
|
-
|
347
|
+
_oj_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line) {
|
366
348
|
int xline = 1;
|
367
349
|
int col = 1;
|
368
350
|
|
data/ext/oj/oj.h
CHANGED
@@ -41,6 +41,7 @@ extern "C" {
|
|
41
41
|
#include "ruby.h"
|
42
42
|
#ifdef HAVE_RUBY_ENCODING_H
|
43
43
|
// HAVE_RUBY_ENCODING_H defined for Ruby 1.9
|
44
|
+
#define IVAR_HELPERS 1
|
44
45
|
#include "ruby/encoding.h"
|
45
46
|
#endif
|
46
47
|
|
@@ -56,9 +57,10 @@ extern "C" {
|
|
56
57
|
#undef T_RATIONAL
|
57
58
|
#undef T_COMPLEX
|
58
59
|
#define NO_RSTRUCT 1
|
60
|
+
#define IVAR_HELPERS 0
|
59
61
|
#endif
|
60
62
|
|
61
|
-
#define raise_error(msg, xml, current)
|
63
|
+
#define raise_error(msg, xml, current) _oj_raise_error(msg, xml, current, __FILE__, __LINE__)
|
62
64
|
|
63
65
|
typedef enum {
|
64
66
|
Yes = 'y',
|
@@ -67,34 +69,33 @@ typedef enum {
|
|
67
69
|
} YesNo;
|
68
70
|
|
69
71
|
typedef enum {
|
72
|
+
StrictMode = 's',
|
70
73
|
ObjectMode = 'o',
|
71
|
-
|
72
|
-
|
74
|
+
NullMode = 'n',
|
75
|
+
CompatMode = 'c'
|
73
76
|
} Mode;
|
74
77
|
|
75
|
-
typedef enum {
|
76
|
-
StrictEffort = 's',
|
77
|
-
TolerantEffort = 't',
|
78
|
-
LazyEffort = 'z',
|
79
|
-
NoEffort = 0,
|
80
|
-
} Effort;
|
81
|
-
|
82
78
|
typedef struct _Options {
|
83
79
|
char encoding[64]; // encoding, stored in the option to avoid GC invalidation in default values
|
84
80
|
int indent; // indention for dump, default 2
|
85
81
|
char circular; // YesNo
|
86
82
|
char mode; // Mode
|
87
|
-
char effort; // Effort
|
88
83
|
} *Options;
|
89
84
|
|
90
|
-
extern VALUE
|
91
|
-
extern char*
|
92
|
-
|
93
|
-
extern void _raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
|
85
|
+
extern VALUE oj_parse(char *json, Options options);
|
86
|
+
extern char* oj_write_obj_to_str(VALUE obj, Options copts);
|
87
|
+
extern void oj_write_obj_to_file(VALUE obj, const char *path, Options copts);
|
94
88
|
|
89
|
+
extern void _oj_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
|
95
90
|
|
96
91
|
extern VALUE Oj;
|
97
92
|
|
93
|
+
extern ID oj_instance_variables_id;
|
94
|
+
extern ID oj_to_hash_id;
|
95
|
+
extern ID oj_to_json_id;
|
96
|
+
extern ID oj_tv_sec_id;
|
97
|
+
extern ID oj_tv_usec_id;
|
98
|
+
|
98
99
|
#if defined(__cplusplus)
|
99
100
|
#if 0
|
100
101
|
{ /* satisfy cc-mode */
|
data/lib/oj/version.rb
CHANGED
data/test/perf_simple.rb
CHANGED
@@ -4,62 +4,284 @@
|
|
4
4
|
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
5
|
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
6
|
|
7
|
-
#require 'test/unit'
|
8
7
|
require 'optparse'
|
9
8
|
require 'yajl'
|
9
|
+
require 'json'
|
10
|
+
require 'json/pure'
|
11
|
+
require 'json/ext'
|
12
|
+
require 'msgpack'
|
10
13
|
require 'oj'
|
14
|
+
require 'ox'
|
15
|
+
|
16
|
+
class Jazz
|
17
|
+
def initialize()
|
18
|
+
@boolean = true
|
19
|
+
@number = 58
|
20
|
+
@string = "A string"
|
21
|
+
@array = [true, false, nil]
|
22
|
+
@hash = { 'one' => 1, 'two' => 2 }
|
23
|
+
end
|
24
|
+
def to_json()
|
25
|
+
%{
|
26
|
+
{ "boolean":#{@boolean},
|
27
|
+
"number":#{@number},
|
28
|
+
"string":#{@string},
|
29
|
+
"array":#{@array},
|
30
|
+
"hash":#{@hash},
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
def to_hash()
|
35
|
+
{ 'boolean' => @boolean,
|
36
|
+
'number' => @number,
|
37
|
+
'string' => @string,
|
38
|
+
'array' => @array,
|
39
|
+
'hash' => @hash,
|
40
|
+
}
|
41
|
+
end
|
42
|
+
def to_msgpack(out)
|
43
|
+
out << MessagePack.pack(to_hash())
|
44
|
+
end
|
45
|
+
end
|
11
46
|
|
12
47
|
$indent = 2
|
48
|
+
$iter = 10000
|
49
|
+
$with_object = true
|
50
|
+
$with_bignum = true
|
51
|
+
$with_nums = true
|
13
52
|
|
14
53
|
opts = OptionParser.new
|
54
|
+
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
55
|
+
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
56
|
+
opts.on("-o", "without objects") { $with_object = false }
|
57
|
+
opts.on("-b", "without bignum") { $with_bignum = false }
|
58
|
+
opts.on("-n", "without numbers") { $with_nums = false }
|
15
59
|
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
16
60
|
files = opts.parse(ARGV)
|
17
61
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
62
|
+
if $with_nums
|
63
|
+
obj = {
|
64
|
+
'a' => 'Alpha',
|
65
|
+
'b' => true,
|
66
|
+
'c' => 12345,
|
67
|
+
'd' => [ true, [false, [12345, nil], 3.967, ['something', false], nil]],
|
68
|
+
'e' => { 'one' => 1, 'two' => 2 },
|
69
|
+
'f' => nil,
|
70
|
+
}
|
71
|
+
obj['g'] = Jazz.new() if $with_object
|
72
|
+
obj['h'] = 12345678901234567890123456789 if $with_bignum
|
73
|
+
else
|
74
|
+
obj = {
|
75
|
+
'a' => 'Alpha',
|
76
|
+
'b' => true,
|
77
|
+
'c' => '12345',
|
78
|
+
'd' => [ true, [false, ['12345', nil], '3.967', ['something', false], nil]],
|
79
|
+
'e' => { 'one' => '1', 'two' => '2' },
|
80
|
+
'f' => nil,
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
Oj.default_options = { :indent => $indent, :mode => :object }
|
85
|
+
|
86
|
+
s = Oj.dump(obj)
|
25
87
|
|
26
|
-
|
88
|
+
xml = Ox.dump(obj, :indent => $indent)
|
27
89
|
|
28
90
|
puts
|
29
91
|
|
92
|
+
# Put Oj in strict mode so it only create JSON native types instead of the
|
93
|
+
# original Ruby Objects. None of the other packages other than Ox support
|
94
|
+
# Object recreation so no need for Oj to do it in the performance tests.
|
95
|
+
Oj.default_options = { :mode => :strict }
|
96
|
+
parse_results = { :oj => 0.0, :yajl => 0.0, :msgpack => 0.0, :pure => 0.0, :ext => 0.0, :ox => 0.0 }
|
97
|
+
|
30
98
|
start = Time.now
|
31
|
-
iter.times do
|
99
|
+
$iter.times do
|
32
100
|
Oj.load(s)
|
33
101
|
end
|
34
|
-
|
35
|
-
|
102
|
+
dt = Time.now - start
|
103
|
+
base_dt = dt
|
104
|
+
parse_results[:oj] = dt
|
105
|
+
puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [$iter, dt, $iter/dt/1000.0]
|
36
106
|
|
37
107
|
start = Time.now
|
38
|
-
iter.times do
|
108
|
+
$iter.times do
|
39
109
|
Yajl::Parser.parse(s)
|
40
110
|
end
|
41
|
-
|
42
|
-
|
111
|
+
dt = Time.now - start
|
112
|
+
if base_dt < dt
|
113
|
+
base_dt = dt
|
114
|
+
base_name = 'Yajl'
|
115
|
+
end
|
116
|
+
parse_results[:yajl] = dt
|
117
|
+
puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parses/msec" % [$iter, dt, $iter/dt/1000.0]
|
118
|
+
|
119
|
+
begin
|
120
|
+
JSON.parser = JSON::Ext::Parser
|
121
|
+
start = Time.now
|
122
|
+
$iter.times do
|
123
|
+
JSON.parse(s)
|
124
|
+
end
|
125
|
+
dt = Time.now - start
|
126
|
+
if base_dt < dt
|
127
|
+
base_dt = dt
|
128
|
+
base_name = 'JSON::Ext'
|
129
|
+
end
|
130
|
+
parse_results[:ext] = dt
|
131
|
+
puts "%d JSON::Ext::Parser parse()s in %0.3f seconds or %0.1f parses/msec" % [$iter, dt, $iter/dt/1000.0]
|
132
|
+
rescue Exception => e
|
133
|
+
puts "JSON::Ext failed: #{e.class}: #{e.message}"
|
134
|
+
end
|
135
|
+
|
136
|
+
begin
|
137
|
+
JSON.parser = JSON::Pure::Parser
|
138
|
+
start = Time.now
|
139
|
+
$iter.times do
|
140
|
+
JSON.parse(s)
|
141
|
+
end
|
142
|
+
dt = Time.now - start
|
143
|
+
if base_dt < dt
|
144
|
+
base_dt = dt
|
145
|
+
base_name = 'JSON::Pure'
|
146
|
+
end
|
147
|
+
parse_results[:pure] = dt
|
148
|
+
puts "%d JSON::Pure::Parser parse()s in %0.3f seconds or %0.1f parses/msec" % [$iter, dt, $iter/dt/1000.0]
|
149
|
+
rescue Exception => e
|
150
|
+
puts "JSON::Pure failed: #{e.class}: #{e.message}"
|
151
|
+
end
|
152
|
+
|
153
|
+
begin
|
154
|
+
mp = MessagePack.pack(obj)
|
155
|
+
start = Time.now
|
156
|
+
$iter.times do
|
157
|
+
MessagePack.unpack(mp)
|
158
|
+
end
|
159
|
+
dt = Time.now - start
|
160
|
+
if base_dt < dt
|
161
|
+
base_dt = dt
|
162
|
+
base_name = 'MessagePack'
|
163
|
+
end
|
164
|
+
parse_results[:msgpack] = dt
|
165
|
+
puts "%d MessagePack.unpack()s in %0.3f seconds or %0.1f packs/msec" % [$iter, dt, $iter/dt/1000.0]
|
166
|
+
rescue Exception => e
|
167
|
+
puts "MessagePack failed: #{e.class}: #{e.message}"
|
168
|
+
end
|
43
169
|
|
44
|
-
|
170
|
+
start = Time.now
|
171
|
+
$iter.times do
|
172
|
+
Ox.load(xml)
|
173
|
+
end
|
174
|
+
dt = Time.now - start
|
175
|
+
parse_results[:ox] = dt
|
176
|
+
puts "%d Ox.load()s in %0.3f seconds or %0.1f loads/msec" % [$iter, dt, $iter/dt/1000.0]
|
177
|
+
|
178
|
+
puts "Parser results:"
|
179
|
+
puts "gem seconds parses/msec X faster than #{base_name} (higher is better)"
|
180
|
+
parse_results.each do |name,dt|
|
181
|
+
if 0.0 == dt
|
182
|
+
puts "#{name} failed to generate JSON"
|
183
|
+
next
|
184
|
+
end
|
185
|
+
puts "%-7s %6.3f %5.1f %4.1f" % [name, dt, $iter/dt/1000.0, base_dt/dt]
|
186
|
+
end
|
45
187
|
|
46
188
|
puts
|
47
189
|
|
48
|
-
|
190
|
+
# Back to object mode for best performance when dumping.
|
191
|
+
Oj.default_options = { :indent => $indent, :mode => :object }
|
192
|
+
dump_results = { :oj => 0.0, :yajl => 0.0, :msgpack => 0.0, :pure => 0.0, :ext => 0.0, :ox => 0.0 }
|
193
|
+
|
49
194
|
start = Time.now
|
50
|
-
iter.times do
|
195
|
+
$iter.times do
|
51
196
|
Oj.dump(obj)
|
52
197
|
end
|
53
|
-
|
54
|
-
|
198
|
+
dt = Time.now - start
|
199
|
+
base_dt = dt
|
200
|
+
base_name = 'Oj'
|
201
|
+
parse_results[:oj] = dt
|
202
|
+
puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [$iter, dt, $iter/dt/1000.0]
|
55
203
|
|
56
204
|
start = Time.now
|
57
|
-
iter.times do
|
205
|
+
$iter.times do
|
58
206
|
Yajl::Encoder.encode(obj)
|
59
207
|
end
|
60
|
-
|
61
|
-
|
208
|
+
dt = Time.now - start
|
209
|
+
if base_dt < dt
|
210
|
+
base_dt = dt
|
211
|
+
base_name = 'Yajl'
|
212
|
+
end
|
213
|
+
parse_results[:yajl] = dt
|
214
|
+
puts "%d Yajl::Encoder.encode()s in %0.3f seconds or %0.1f encodes/msec" % [$iter, dt, $iter/dt/1000.0]
|
215
|
+
|
216
|
+
begin
|
217
|
+
JSON.parser = JSON::Ext::Parser
|
218
|
+
start = Time.now
|
219
|
+
$iter.times do
|
220
|
+
JSON.generate(obj)
|
221
|
+
end
|
222
|
+
dt = Time.now - start
|
223
|
+
if base_dt < dt
|
224
|
+
base_dt = dt
|
225
|
+
base_name = 'JSON::Ext'
|
226
|
+
end
|
227
|
+
parse_results[:pure] = dt
|
228
|
+
puts "%d JSON::Ext generate()s in %0.3f seconds or %0.1f generates/msec" % [$iter, dt, $iter/dt/1000.0]
|
229
|
+
rescue Exception => e
|
230
|
+
parse_results[:ext] = 0.0
|
231
|
+
puts "JSON::Ext failed: #{e.class}: #{e.message}"
|
232
|
+
end
|
62
233
|
|
63
|
-
|
234
|
+
begin
|
235
|
+
JSON.parser = JSON::Pure::Parser
|
236
|
+
start = Time.now
|
237
|
+
$iter.times do
|
238
|
+
JSON.generate(obj)
|
239
|
+
end
|
240
|
+
dt = Time.now - start
|
241
|
+
if base_dt < dt
|
242
|
+
base_dt = dt
|
243
|
+
base_name = 'JSON::Pure'
|
244
|
+
end
|
245
|
+
parse_results[:pure] = dt
|
246
|
+
puts "%d JSON::Pure generate()s in %0.3f seconds or %0.1f generates/msec" % [$iter, dt, $iter/dt/1000.0]
|
247
|
+
rescue Exception => e
|
248
|
+
parse_results[:pure] = 0.0
|
249
|
+
puts "JSON::Pure failed: #{e.class}: #{e.message}"
|
250
|
+
end
|
251
|
+
|
252
|
+
begin
|
253
|
+
start = Time.now
|
254
|
+
$iter.times do
|
255
|
+
MessagePack.pack(obj)
|
256
|
+
end
|
257
|
+
dt = Time.now - start
|
258
|
+
if base_dt < dt
|
259
|
+
base_dt = dt
|
260
|
+
base_name = 'MessagePack'
|
261
|
+
end
|
262
|
+
parse_results[:msgpack] = dt
|
263
|
+
puts "%d Msgpack()s in %0.3f seconds or %0.1f unpacks/msec" % [$iter, dt, $iter/dt/1000.0]
|
264
|
+
rescue Exception => e
|
265
|
+
parse_results[:msgpack] = 0.0
|
266
|
+
puts "MessagePack failed: #{e.class}: #{e.message}"
|
267
|
+
end
|
268
|
+
|
269
|
+
start = Time.now
|
270
|
+
$iter.times do
|
271
|
+
Ox.dump(obj)
|
272
|
+
end
|
273
|
+
dt = Time.now - start
|
274
|
+
parse_results[:ox] = dt
|
275
|
+
puts "%d Ox.dump()s in %0.3f seconds or %0.1f dumps/msec" % [$iter, dt, $iter/dt/1000.0]
|
276
|
+
|
277
|
+
puts "Parser results:"
|
278
|
+
puts "gem seconds dumps/msec X faster than #{base_name} (higher is better)"
|
279
|
+
parse_results.each do |name,dt|
|
280
|
+
if 0.0 == dt
|
281
|
+
puts "#{name} failed to generate JSON"
|
282
|
+
next
|
283
|
+
end
|
284
|
+
puts "%-7s %6.3f %5.1f %4.1f" % [name, dt, $iter/dt/1000.0, base_dt/dt]
|
285
|
+
end
|
64
286
|
|
65
287
|
puts
|