oj 1.2.5 → 1.2.6
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 +4 -2
- data/ext/oj/extconf.rb +1 -1
- data/ext/oj/fast.c +4 -0
- data/ext/oj/oj.c +167 -24
- data/ext/oj/oj.h +2 -0
- data/lib/oj.rb +23 -31
- data/lib/oj/version.rb +1 -1
- data/test/boo.rb +26 -0
- data/test/{perf2.rb → foo.rb} +12 -30
- data/test/where.rb +54 -0
- metadata +6 -6
- data/test/perf1.rb +0 -64
- data/test/perf_obj_old.rb +0 -213
data/README.md
CHANGED
@@ -24,9 +24,11 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
24
24
|
|
25
25
|
## <a name="release">Release Notes</a>
|
26
26
|
|
27
|
-
### Release 1.2.
|
27
|
+
### Release 1.2.6
|
28
28
|
|
29
|
-
-
|
29
|
+
- Cleaned up documentation errors.
|
30
|
+
|
31
|
+
- Added support for OS X Ruby 1.8.7.
|
30
32
|
|
31
33
|
## <a name="description">Description</a>
|
32
34
|
|
data/ext/oj/extconf.rb
CHANGED
@@ -20,7 +20,7 @@ dflags = {
|
|
20
20
|
'HAS_ENCODING_SUPPORT' => (('ruby' == type || 'rubinius' == type) && '1' == version[0] && '9' == version[1]) ? 1 : 0,
|
21
21
|
'HAS_NANO_TIME' => ('ruby' == type && '1' == version[0] && '9' == version[1]) ? 1 : 0,
|
22
22
|
'HAS_RSTRUCT' => ('ruby' == type || 'ree' == type) ? 1 : 0,
|
23
|
-
'HAS_IVAR_HELPERS' => ('ruby' == type && '1' == version[0] && '9' == version[1]) ? 1 : 0,
|
23
|
+
'HAS_IVAR_HELPERS' => ('ruby' == type && '1' == version[0] && '9' == version[1] && '2' <= version[2]) ? 1 : 0,
|
24
24
|
'HAS_PROC_WITH_BLOCK' => ('ruby' == type && '1' == version[0] && '9' == version[1]) ? 1 : 0,
|
25
25
|
'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
|
26
26
|
}
|
data/ext/oj/fast.c
CHANGED
data/ext/oj/oj.c
CHANGED
@@ -93,7 +93,6 @@ static VALUE space_sym;
|
|
93
93
|
static VALUE symbolize_names_sym;
|
94
94
|
|
95
95
|
static VALUE mimic = Qnil;
|
96
|
-
static VALUE keep = Qnil;
|
97
96
|
|
98
97
|
Cache oj_class_cache = 0;
|
99
98
|
Cache oj_attr_cache = 0;
|
@@ -370,6 +369,16 @@ load(int argc, VALUE *argv, VALUE self) {
|
|
370
369
|
return load_with_opts(*argv, &options);
|
371
370
|
}
|
372
371
|
|
372
|
+
/* Document-method: load_file
|
373
|
+
* call-seq: load_file(path, options) => Hash, Array, String, Fixnum, Float, true, false, or nil
|
374
|
+
*
|
375
|
+
* Parses a JSON document from a file into a Hash, Array, String, Fixnum,
|
376
|
+
* Float, true, false, or nil. Raises an exception if the JSON is malformed or
|
377
|
+
* the classes specified are not valid.
|
378
|
+
*
|
379
|
+
* @param [String] path path to a file containing a JSON document
|
380
|
+
* @param [Hash] options load options (same as default_options)
|
381
|
+
*/
|
373
382
|
static VALUE
|
374
383
|
load_file(int argc, VALUE *argv, VALUE self) {
|
375
384
|
char *path;
|
@@ -648,7 +657,7 @@ mimic_parse(int argc, VALUE *argv, VALUE self) {
|
|
648
657
|
struct _Options options = oj_default_options;
|
649
658
|
|
650
659
|
if (1 > argc) {
|
651
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to
|
660
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to parse().\n");
|
652
661
|
}
|
653
662
|
if (2 <= argc && Qnil != argv[1]) {
|
654
663
|
VALUE ropts = argv[1];
|
@@ -703,7 +712,8 @@ mimic_create_id(VALUE self, VALUE id) {
|
|
703
712
|
return id;
|
704
713
|
}
|
705
714
|
|
706
|
-
/*
|
715
|
+
/* Document-method: mimic_JSON
|
716
|
+
* call-seq: mimic_JSON() => Module
|
707
717
|
*
|
708
718
|
* Creates the JSON module with methods and classes to mimic the JSON
|
709
719
|
* gem. After this method is invoked calls that expect the JSON module will
|
@@ -715,11 +725,12 @@ static VALUE
|
|
715
725
|
define_mimic_json(VALUE self) {
|
716
726
|
if (Qnil == mimic) {
|
717
727
|
VALUE ext;
|
728
|
+
VALUE dummy;
|
718
729
|
|
719
730
|
mimic = rb_define_module("JSON");
|
720
731
|
ext = rb_define_module_under(mimic, "Ext");
|
721
|
-
rb_define_class_under(ext, "Parser", rb_cObject);
|
722
|
-
rb_define_class_under(ext, "Generator", rb_cObject);
|
732
|
+
dummy = rb_define_class_under(ext, "Parser", rb_cObject);
|
733
|
+
dummy = rb_define_class_under(ext, "Generator", rb_cObject);
|
723
734
|
|
724
735
|
rb_define_module_function(mimic, "parser=", no_op1, 1);
|
725
736
|
rb_define_module_function(mimic, "generator=", no_op1, 1);
|
@@ -736,12 +747,12 @@ define_mimic_json(VALUE self) {
|
|
736
747
|
rb_define_module_function(mimic, "parse", mimic_parse, -1);
|
737
748
|
rb_define_module_function(mimic, "parse!", mimic_parse, -1);
|
738
749
|
|
739
|
-
array_nl_sym = ID2SYM(rb_intern("array_nl"));
|
740
|
-
create_additions_sym = ID2SYM(rb_intern("create_additions"));
|
741
|
-
object_nl_sym = ID2SYM(rb_intern("object_nl"));
|
742
|
-
space_before_sym = ID2SYM(rb_intern("space_before"));
|
743
|
-
space_sym = ID2SYM(rb_intern("space"));
|
744
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
|
750
|
+
array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&array_nl_sym);
|
751
|
+
create_additions_sym = ID2SYM(rb_intern("create_additions")); rb_gc_register_address(&create_additions_sym);
|
752
|
+
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
753
|
+
space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&space_before_sym);
|
754
|
+
space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&space_sym);
|
755
|
+
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
745
756
|
|
746
757
|
oj_default_options.mode = CompatMode;
|
747
758
|
oj_default_options.ascii_only = Yes;
|
@@ -751,7 +762,6 @@ define_mimic_json(VALUE self) {
|
|
751
762
|
|
752
763
|
void Init_oj() {
|
753
764
|
Oj = rb_define_module("Oj");
|
754
|
-
keep = rb_cv_get(Oj, "@@keep"); // needed to stop GC from deleting and reusing VALUEs
|
755
765
|
|
756
766
|
rb_require("time");
|
757
767
|
rb_require("date");
|
@@ -786,19 +796,19 @@ void Init_oj() {
|
|
786
796
|
oj_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
|
787
797
|
oj_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
788
798
|
|
789
|
-
ascii_only_sym = ID2SYM(rb_intern("ascii_only"));
|
790
|
-
auto_define_sym = ID2SYM(rb_intern("auto_define"));
|
791
|
-
circular_sym = ID2SYM(rb_intern("circular"));
|
792
|
-
compat_sym = ID2SYM(rb_intern("compat"));
|
793
|
-
create_id_sym = ID2SYM(rb_intern("create_id"));
|
794
|
-
indent_sym = ID2SYM(rb_intern("indent"));
|
795
|
-
mode_sym = ID2SYM(rb_intern("mode"));
|
796
|
-
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
|
797
|
-
null_sym = ID2SYM(rb_intern("null"));
|
798
|
-
object_sym = ID2SYM(rb_intern("object"));
|
799
|
-
strict_sym = ID2SYM(rb_intern("strict"));
|
799
|
+
ascii_only_sym = ID2SYM(rb_intern("ascii_only")); rb_gc_register_address(&ascii_only_sym);
|
800
|
+
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
|
801
|
+
circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
|
802
|
+
compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
|
803
|
+
create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
|
804
|
+
indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
|
805
|
+
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
806
|
+
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
|
807
|
+
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
808
|
+
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
809
|
+
strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
|
800
810
|
|
801
|
-
oj_slash_string = rb_str_new2("/");
|
811
|
+
oj_slash_string = rb_str_new2("/"); rb_gc_register_address(&oj_slash_string);
|
802
812
|
|
803
813
|
oj_default_options.mode = ObjectMode;
|
804
814
|
#if HAS_ENCODING_SUPPORT
|
@@ -827,3 +837,136 @@ _oj_raise_error(const char *msg, const char *xml, const char *current, const cha
|
|
827
837
|
rb_raise(rb_eSyntaxError, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
|
828
838
|
}
|
829
839
|
|
840
|
+
// mimic JSON documentation
|
841
|
+
|
842
|
+
/* Document-module: JSON
|
843
|
+
*
|
844
|
+
* JSON is a JSON parser. This module when defined by the Oj module is a
|
845
|
+
* faster replacement for the original.
|
846
|
+
*/
|
847
|
+
/* Document-module: JSON::Ext
|
848
|
+
*
|
849
|
+
* The Ext module is a placeholder in the mimic JSON module used for
|
850
|
+
* compatibility only.
|
851
|
+
*/
|
852
|
+
/* Document-class: JSON::Ext::Parser
|
853
|
+
*
|
854
|
+
* The JSON::Ext::Parser is a placeholder in the mimic JSON module used for
|
855
|
+
* compatibility only.
|
856
|
+
*/
|
857
|
+
/* Document-class: JSON::Ext::Generator
|
858
|
+
*
|
859
|
+
* The JSON::Ext::Generator is a placeholder in the mimic JSON module used for
|
860
|
+
* compatibility only.
|
861
|
+
*/
|
862
|
+
|
863
|
+
/* Document-method: create_id=
|
864
|
+
* call-seq: create_id=(id) -> String
|
865
|
+
*
|
866
|
+
* Sets the create_id tag to look for in JSON document. That key triggers the
|
867
|
+
* creation of a class with the same name.
|
868
|
+
*
|
869
|
+
* @param [nil|String] id new create_id
|
870
|
+
* @return the id
|
871
|
+
*/
|
872
|
+
/* Document-method: parser=
|
873
|
+
* call-seq: parser=(parser) -> nil
|
874
|
+
*
|
875
|
+
* Does nothing other than provide compatibiltiy.
|
876
|
+
* @param [Object] parser ignored
|
877
|
+
*/
|
878
|
+
/* Document-method: generator=
|
879
|
+
* call-seq: generator=(generator) -> nil
|
880
|
+
*
|
881
|
+
* Does nothing other than provide compatibiltiy.
|
882
|
+
* @param [Object] generator ignored
|
883
|
+
*/
|
884
|
+
/* Document-method: dump
|
885
|
+
* call-seq: dump(obj, anIO=nil, limit = nil) -> String
|
886
|
+
*
|
887
|
+
* Encodes an object as a JSON String.
|
888
|
+
*
|
889
|
+
* @param [Object] obj object to convert to encode as JSON
|
890
|
+
* @param [IO] anIO an IO that allows writing
|
891
|
+
* @param [Fixnum] limit ignored
|
892
|
+
*/
|
893
|
+
/* Document-method: load
|
894
|
+
* call-seq: load(source, proc=nil) -> Object
|
895
|
+
*
|
896
|
+
* Loads a Ruby Object from a JSON source that can be either a String or an
|
897
|
+
* IO. If Proc is given or a block is providedit is called with each nested
|
898
|
+
* element of the loaded Object.
|
899
|
+
*
|
900
|
+
* @param [String|IO] source JSON source
|
901
|
+
* @param [Proc] proc to yield to on each element or nil
|
902
|
+
*/
|
903
|
+
/* Document-method: restore
|
904
|
+
* call-seq: restore(source, proc=nil) -> Object
|
905
|
+
*
|
906
|
+
* Loads a Ruby Object from a JSON source that can be either a String or an
|
907
|
+
* IO. If Proc is given or a block is providedit is called with each nested
|
908
|
+
* element of the loaded Object.
|
909
|
+
*
|
910
|
+
* @param [String|IO] source JSON source
|
911
|
+
* @param [Proc] proc to yield to on each element or nil
|
912
|
+
*/
|
913
|
+
/* Document-method: recurse_proc
|
914
|
+
* call-seq: recurse_proc(obj, &proc) -> nil
|
915
|
+
*
|
916
|
+
* Yields to the proc for every element in the obj recursivly.
|
917
|
+
*
|
918
|
+
* @param [Hash|Array] obj object to walk
|
919
|
+
* @param [Proc] proc to yield to on each element
|
920
|
+
*/
|
921
|
+
/* Document-method: []
|
922
|
+
* call-seq: [](obj, opts={}) -> Object
|
923
|
+
*
|
924
|
+
* If the obj argument is a String then it is assumed to be a JSON String and
|
925
|
+
* parsed otherwise the obj is encoded as a JSON String.
|
926
|
+
*
|
927
|
+
* @param [String|Hash|Array] obj object to convert
|
928
|
+
* @param [Hash] opts same options as either generate or parse
|
929
|
+
*/
|
930
|
+
/* Document-method: generate
|
931
|
+
* call-seq: generate(obj, opts=nil) -> String
|
932
|
+
*
|
933
|
+
* Encode obj as a JSON String. The obj argument must be a Hash, Array, or
|
934
|
+
* respond to to_h or to_json. Options other than those listed such as
|
935
|
+
* +:allow_nan+ or +:max_nesting+ are ignored.
|
936
|
+
*
|
937
|
+
* @param [Object|Hash|Array] obj object to convert to a JSON String
|
938
|
+
* @param [Hash] opts options
|
939
|
+
* @param [String] :indent String to use for indentation
|
940
|
+
* @param [String] :space String placed after a , or : delimiter
|
941
|
+
* @param [String] :space_before String placed before a : delimiter
|
942
|
+
* @param [String] :object_nl String placed after a JSON object
|
943
|
+
* @param [String] :array_nl String placed after a JSON array
|
944
|
+
*/
|
945
|
+
/* Document-method: fast_generate
|
946
|
+
* call-seq: fast_generate(obj, opts=nil) -> String
|
947
|
+
* Same as generate().
|
948
|
+
* @see generate
|
949
|
+
*/
|
950
|
+
/* Document-method: pretty_generate
|
951
|
+
* call-seq: pretty_generate(obj, opts=nil) -> String
|
952
|
+
* Same as generate() but with different defaults for the spacing options.
|
953
|
+
* @see generate
|
954
|
+
*/
|
955
|
+
/* Document-method: parse
|
956
|
+
* call-seq: parse(source, opts=nil) -> Object
|
957
|
+
*
|
958
|
+
* Parses a JSON String or IO into a Ruby Object. Options other than those
|
959
|
+
* listed such as +:allow_nan+ or +:max_nesting+ are ignored. +:object_class+ and
|
960
|
+
* +:array_object+ are not supported.
|
961
|
+
*
|
962
|
+
* @param [String|IO] source source to parse
|
963
|
+
* @param [Hash] opts options
|
964
|
+
* @param [true|false] :symbolize_names flag indicating JSON object keys should be Symbols instead of Strings
|
965
|
+
* @param [true|false] :create_additions flag indicating a key matching +create_id+ in a JSON object should trigger the creation of Ruby Object
|
966
|
+
* @see create_id=
|
967
|
+
*/
|
968
|
+
/* Document-method: parse!
|
969
|
+
* call-seq: parse!(source, opts=nil) -> Object
|
970
|
+
* Same as parse().
|
971
|
+
* @see parse
|
972
|
+
*/
|
data/ext/oj/oj.h
CHANGED
data/lib/oj.rb
CHANGED
@@ -1,35 +1,27 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# -
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# -
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
|
1
|
+
# Optimized JSON (Oj), as the name implies was written to provide speed
|
2
|
+
# optimized JSON handling.
|
3
|
+
#
|
4
|
+
# Oj has several dump or serialization modes which control how Objects are
|
5
|
+
# converted to JSON. These modes are set with the :effort option in either the
|
6
|
+
# default options or as one of the options to the dump() method.
|
7
|
+
#
|
8
|
+
# - :strict mode will only allow the 7 basic JSON types to be serialized. Any other Object
|
9
|
+
# will raise and Exception.
|
10
|
+
#
|
11
|
+
# - :null mode replaces any Object that is not one of the JSON types is replaced by a JSON null.
|
12
|
+
#
|
13
|
+
# - :object mode will dump any Object as a JSON Object with keys that match
|
14
|
+
# the Ruby Object's variable names without the '@' character. This is the
|
15
|
+
# highest performance mode.
|
16
|
+
#
|
17
|
+
# - :compat mode is is the compatible with other systems. It will serialize
|
18
|
+
# any Object but will check to see if the Object implements a to_hash() or
|
19
|
+
# to_json() method. If either exists that method is used for serializing the
|
20
|
+
# Object. The to_hash() is more flexible and produces more consistent output
|
21
|
+
# so it has a preference over the to_json() method. If neither the to_json()
|
22
|
+
# or to_hash() methods exist then the Oj internal Object variable encoding
|
23
|
+
# is used.
|
30
24
|
module Oj
|
31
|
-
private
|
32
|
-
@@keep = []
|
33
25
|
end
|
34
26
|
|
35
27
|
require 'oj/version'
|
data/lib/oj/version.rb
CHANGED
data/test/boo.rb
ADDED
@@ -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]
|
data/test/{perf2.rb → foo.rb}
RENAMED
@@ -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
|
-
|
51
|
-
puts "%d Oj.load()s in %0.3f seconds or %0.1f loads/msec" % [iter,
|
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
|
-
|
58
|
-
puts "%d Yajl::Parser.parse()s in %0.3f seconds or %0.1f parses/msec" % [iter,
|
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
|
-
|
67
|
-
puts "%d Oj.dump()s in %0.3f seconds or %0.1f dumps/msec" % [iter,
|
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
|
-
|
74
|
-
puts "%d Yajl::Encoder.encode()s in %0.3f seconds or %0.1f encodes/msec" % [iter,
|
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]
|
data/test/where.rb
ADDED
@@ -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,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-22 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'The fastest JSON parser and object serializer. '
|
15
15
|
email: peter@ohler.com
|
@@ -32,13 +32,12 @@ files:
|
|
32
32
|
- ext/oj/fast.c
|
33
33
|
- ext/oj/load.c
|
34
34
|
- ext/oj/oj.c
|
35
|
+
- test/boo.rb
|
35
36
|
- test/files.rb
|
37
|
+
- test/foo.rb
|
36
38
|
- test/perf.rb
|
37
|
-
- test/perf1.rb
|
38
|
-
- test/perf2.rb
|
39
39
|
- test/perf_fast.rb
|
40
40
|
- test/perf_obj.rb
|
41
|
-
- test/perf_obj_old.rb
|
42
41
|
- test/perf_simple.rb
|
43
42
|
- test/perf_strict.rb
|
44
43
|
- test/sample/change.rb
|
@@ -58,6 +57,7 @@ files:
|
|
58
57
|
- test/test_fast.rb
|
59
58
|
- test/test_mimic.rb
|
60
59
|
- test/tests.rb
|
60
|
+
- test/where.rb
|
61
61
|
- LICENSE
|
62
62
|
- README.md
|
63
63
|
homepage: http://www.ohler.com/oj
|
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
83
|
version: '0'
|
84
84
|
requirements: []
|
85
85
|
rubyforge_project: oj
|
86
|
-
rubygems_version: 1.8.
|
86
|
+
rubygems_version: 1.8.11
|
87
87
|
signing_key:
|
88
88
|
specification_version: 3
|
89
89
|
summary: A fast JSON parser and serializer.
|
data/test/perf1.rb
DELETED
@@ -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
|
data/test/perf_obj_old.rb
DELETED
@@ -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
|