ffi-yajl 2.7.5-universal-mingw-ucrt

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +118 -0
  4. data/bin/ffi-yajl-bench +36 -0
  5. data/ext/ffi_yajl/ext/dlopen/dlopen.c +40 -0
  6. data/ext/ffi_yajl/ext/dlopen/extconf.rb +16 -0
  7. data/ext/ffi_yajl/ext/dlopen/yajl.sym +18 -0
  8. data/ext/ffi_yajl/ext/encoder/encoder.c +395 -0
  9. data/ext/ffi_yajl/ext/encoder/extconf.rb +86 -0
  10. data/ext/ffi_yajl/ext/parser/extconf.rb +86 -0
  11. data/ext/ffi_yajl/ext/parser/parser.c +240 -0
  12. data/lib/ffi_yajl/benchmark/MIT-LICENSE +20 -0
  13. data/lib/ffi_yajl/benchmark/encode.rb +82 -0
  14. data/lib/ffi_yajl/benchmark/encode_json_and_marshal.rb +42 -0
  15. data/lib/ffi_yajl/benchmark/encode_json_and_yaml.rb +47 -0
  16. data/lib/ffi_yajl/benchmark/encode_profile.rb +34 -0
  17. data/lib/ffi_yajl/benchmark/http.rb +28 -0
  18. data/lib/ffi_yajl/benchmark/parse.rb +93 -0
  19. data/lib/ffi_yajl/benchmark/parse_json_and_marshal.rb +50 -0
  20. data/lib/ffi_yajl/benchmark/parse_json_and_yaml.rb +55 -0
  21. data/lib/ffi_yajl/benchmark/parse_profile.rb +33 -0
  22. data/lib/ffi_yajl/benchmark/parse_profile_ruby_prof.rb +34 -0
  23. data/lib/ffi_yajl/benchmark/parse_stream.rb +54 -0
  24. data/lib/ffi_yajl/benchmark/subjects/item.json +1 -0
  25. data/lib/ffi_yajl/benchmark/subjects/ohai.json +1216 -0
  26. data/lib/ffi_yajl/benchmark/subjects/ohai.marshal_dump +0 -0
  27. data/lib/ffi_yajl/benchmark/subjects/ohai.yml +975 -0
  28. data/lib/ffi_yajl/benchmark/subjects/twitter_search.json +1 -0
  29. data/lib/ffi_yajl/benchmark/subjects/twitter_stream.json +430 -0
  30. data/lib/ffi_yajl/benchmark/subjects/unicode.json +1 -0
  31. data/lib/ffi_yajl/benchmark.rb +27 -0
  32. data/lib/ffi_yajl/encoder.rb +94 -0
  33. data/lib/ffi_yajl/ext/.keep +0 -0
  34. data/lib/ffi_yajl/ext.rb +49 -0
  35. data/lib/ffi_yajl/ffi/encoder.rb +262 -0
  36. data/lib/ffi_yajl/ffi/parser.rb +163 -0
  37. data/lib/ffi_yajl/ffi.rb +153 -0
  38. data/lib/ffi_yajl/map_library_name.rb +109 -0
  39. data/lib/ffi_yajl/parser.rb +91 -0
  40. data/lib/ffi_yajl/platform.rb +29 -0
  41. data/lib/ffi_yajl/version.rb +25 -0
  42. data/lib/ffi_yajl.rb +50 -0
  43. metadata +128 -0
@@ -0,0 +1,86 @@
1
+ # rubocop:disable Style/GlobalVars
2
+ require "mkmf"
3
+ require "rubygems"
4
+ require "libyajl2"
5
+
6
+ RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
7
+
8
+ # pick up the vendored libyajl2 out of the libyajl2 gem
9
+ $CFLAGS = " -I#{Libyajl2.include_path} #{$CFLAGS}"
10
+ $LDFLAGS = " -L#{Libyajl2.opt_path} #{$LDFLAGS}"
11
+
12
+ # remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen
13
+ $LDFLAGS.slice!("-Wl,--no-undefined")
14
+
15
+ puts $CFLAGS
16
+ puts $LDFLAGS
17
+
18
+ # except if you're doing an unoptimized gcc install we're going to help you out a bit
19
+ if RbConfig::MAKEFILE_CONFIG["CC"] =~ /gcc|clang/
20
+ $CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
21
+ # how many people realize that -Wall is a compiler-specific flag???
22
+ # apparently not many based on reading lots of shitty extconf.rb's out there
23
+ $CFLAGS << " -Wall"
24
+ end
25
+
26
+ def windows?
27
+ !!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/)
28
+ end
29
+
30
+ def macos?
31
+ !!(RUBY_PLATFORM =~ /darwin/)
32
+ end
33
+
34
+ def clang?
35
+ cc_version = `#{RbConfig.expand("$(CC) --version")}`
36
+ cc_version.match?(/clang/i)
37
+ end
38
+
39
+ # XCode 14 warns if `-Wl,-undefined dynamic_lookup` is specified, and as
40
+ # a result Ruby interpreters compiled under XCode 14 no longer specify
41
+ # this flag by default in DLDFLAGS. Let's specify the list of dynamic symbols
42
+ # here to avoid compilation failures.
43
+ if clang? && macos?
44
+ symfile = File.join(__dir__, "../dlopen/yajl.sym")
45
+ dynamic_symbols = File.readlines(symfile)
46
+ dynamic_symbols.each do |sym|
47
+ $DLDFLAGS << " -Wl,-U,#{sym.strip}"
48
+ end
49
+ end
50
+
51
+ if windows?
52
+ # include our libyajldll.a definitions on windows in the libyajl2 gem
53
+ $libs = "#{$libs} -lyajldll"
54
+ end
55
+
56
+ # NOTE: find_library has the side effect of adding -lyajl to the flags which we are deliberately
57
+ # avoiding doing with the libyajl2-gem (allowing it to be lazily loaded with dlopen)
58
+ if !windows? && !find_header("yajl/yajl_tree.h")
59
+ puts "libyajl2 headers not found in libyajl2-gem, searching for system libraries..."
60
+
61
+ HEADER_DIRS = [
62
+ "/opt/local/include", # MacPorts
63
+ "/usr/local/include", # /usr/local
64
+ RbConfig::CONFIG["includedir"], # Ruby
65
+ "/usr/include", # (default)
66
+ ].freeze
67
+
68
+ LIB_DIRS = [
69
+ "/opt/local/lib", # MacPorts
70
+ "/usr/local/lib", # /usr/local + Homebrew
71
+ RbConfig::CONFIG["libdir"], # Ruby
72
+ "/usr/lib", # (default)
73
+ ].freeze
74
+
75
+ # add --with-yajl-dir, --with-yajl-include, --with-yajl-lib
76
+ dir_config("yajl", HEADER_DIRS, LIB_DIRS)
77
+
78
+ # here we use find_library in order to deliberately link with -lyajl as a useful side-effect
79
+ unless find_header("yajl/yajl_tree.h") && find_library("yajl", "yajl_complete_parse")
80
+ abort "libyajl2 is missing. please install libyajl2"
81
+ end
82
+ end
83
+
84
+ dir_config "encoder"
85
+
86
+ create_makefile "ffi_yajl/ext/encoder"
@@ -0,0 +1,86 @@
1
+ # rubocop:disable Style/GlobalVars
2
+ require "mkmf"
3
+ require "rubygems"
4
+ require "libyajl2"
5
+
6
+ RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
7
+
8
+ # pick up the vendored libyajl2 out of the libyajl2 gem
9
+ $CFLAGS = "-I#{Libyajl2.include_path} #{$CFLAGS}"
10
+ $LDFLAGS = "-L#{Libyajl2.opt_path} #{$LDFLAGS}"
11
+
12
+ # remove "-Wl,--no-undefined" flag if existent to allow for loading with dlopen
13
+ $LDFLAGS.slice!("-Wl,--no-undefined")
14
+
15
+ puts $CFLAGS
16
+ puts $LDFLAGS
17
+
18
+ # except if you're doing an unoptimized gcc install we're going to help you out a bit
19
+ if RbConfig::MAKEFILE_CONFIG["CC"] =~ /gcc|clang/
20
+ $CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
21
+ # how many people realize that -Wall is a compiler-specific flag???
22
+ # apparently not many based on reading lots of shitty extconf.rb's out there
23
+ $CFLAGS << " -Wall"
24
+ end
25
+
26
+ def windows?
27
+ !!(RUBY_PLATFORM =~ /mswin|mingw|cygwin|windows/)
28
+ end
29
+
30
+ def macos?
31
+ !!(RUBY_PLATFORM =~ /darwin/)
32
+ end
33
+
34
+ def clang?
35
+ cc_version = `#{RbConfig.expand("$(CC) --version")}`
36
+ cc_version.match?(/clang/i)
37
+ end
38
+
39
+ # XCode 14 warns if `-Wl,-undefined dynamic_lookup` is specified, and as
40
+ # a result Ruby interpreters compiled under XCode 14 no longer specify
41
+ # this flag by default in DLDFLAGS. Let's specify the list of dynamic symbols
42
+ # here to avoid compilation failures.
43
+ if clang? && macos?
44
+ symfile = File.join(__dir__, "../dlopen/yajl.sym")
45
+ dynamic_symbols = File.readlines(symfile)
46
+ dynamic_symbols.each do |sym|
47
+ $DLDFLAGS << " -Wl,-U,#{sym.strip}"
48
+ end
49
+ end
50
+
51
+ if windows?
52
+ # include our libyajldll.a definitions on windows in the libyajl2 gem
53
+ $libs = "#{$libs} -lyajldll"
54
+ end
55
+
56
+ # NOTE: find_library has the side effect of adding -lyajl to the flags which we are deliberately
57
+ # avoiding doing with the libyajl2-gem (allowing it to be lazily loaded with dlopen)
58
+ if !windows? && !find_header("yajl/yajl_tree.h")
59
+ puts "libyajl2 headers not found in libyajl2-gem, searching for system libraries..."
60
+
61
+ HEADER_DIRS = [
62
+ "/opt/local/include", # MacPorts
63
+ "/usr/local/include", # /usr/local
64
+ RbConfig::CONFIG["includedir"], # Ruby
65
+ "/usr/include", # (default)
66
+ ].freeze
67
+
68
+ LIB_DIRS = [
69
+ "/opt/local/lib", # MacPorts
70
+ "/usr/local/lib", # /usr/local + Homebrew
71
+ RbConfig::CONFIG["libdir"], # Ruby
72
+ "/usr/lib", # (default)
73
+ ].freeze
74
+
75
+ # add --with-yajl-dir, --with-yajl-include, --with-yajl-lib
76
+ dir_config("yajl", HEADER_DIRS, LIB_DIRS)
77
+
78
+ # here we use find_library in order to deliberately link with -lyajl as a useful side-effect
79
+ unless find_header("yajl/yajl_tree.h") && find_library("yajl", "yajl_complete_parse")
80
+ abort "libyajl2 is missing. please install libyajl2"
81
+ end
82
+ end
83
+
84
+ dir_config "parser"
85
+
86
+ create_makefile "ffi_yajl/ext/parser"
@@ -0,0 +1,240 @@
1
+ #include <ruby.h>
2
+ #include <yajl/yajl_parse.h>
3
+
4
+ #ifdef HAVE_RUBY_ENCODING_H
5
+ #include <ruby/encoding.h>
6
+ static rb_encoding *utf8Encoding;
7
+ #endif
8
+
9
+ static VALUE mFFI_Yajl, mExt, mParser, cParseError;
10
+
11
+ typedef struct {
12
+ VALUE self;
13
+ int symbolizeKeys;
14
+ int uniqueKeyChecking;
15
+ } CTX;
16
+
17
+ void set_value(CTX *ctx, VALUE val) {
18
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
19
+ VALUE key = rb_ivar_get(ctx->self, rb_intern("key"));
20
+ long len = RARRAY_LEN(stack);
21
+ VALUE last = rb_ary_entry(stack, len-1);
22
+ switch (TYPE(last)) {
23
+ case T_ARRAY:
24
+ rb_ary_push(last, val);
25
+ break;
26
+ case T_HASH:
27
+ if ( ctx->uniqueKeyChecking ) {
28
+ ID sym_has_key = rb_intern("has_key?");
29
+ if ( rb_funcall(last, sym_has_key, 1, key) == Qtrue ) {
30
+ rb_raise(cParseError, "repeated key: %s", RSTRING_PTR(key));
31
+ }
32
+ }
33
+ rb_hash_aset(last, key, val);
34
+ break;
35
+ default:
36
+ rb_ary_push(stack, val);
37
+ break;
38
+ }
39
+ }
40
+
41
+ void set_key(CTX *ctx, VALUE key) {
42
+ rb_ivar_set(ctx->self, rb_intern("key"), key);
43
+ }
44
+
45
+ void start_object(CTX *ctx, VALUE obj) {
46
+ VALUE key_stack = rb_ivar_get(ctx->self, rb_intern("key_stack"));
47
+ VALUE key = rb_ivar_get(ctx->self, rb_intern("key"));
48
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
49
+
50
+ rb_ary_push(key_stack, key);
51
+ rb_ary_push(stack, obj);
52
+ }
53
+
54
+ void end_object(CTX *ctx) {
55
+ VALUE key_stack = rb_ivar_get(ctx->self, rb_intern("key_stack"));
56
+ VALUE stack = rb_ivar_get(ctx->self, rb_intern("stack"));
57
+ rb_ivar_set(ctx->self, rb_intern("key"), rb_ary_pop(key_stack));
58
+ if ( RARRAY_LEN(stack) > 1 ) {
59
+ set_value(ctx, rb_ary_pop(stack));
60
+ }
61
+ }
62
+
63
+ int null_callback(void *ctx) {
64
+ set_value(ctx, Qnil);
65
+ return 1;
66
+ }
67
+
68
+ int boolean_callback(void *ctx, int boolean) {
69
+ set_value(ctx, boolean ? Qtrue : Qfalse);
70
+ return 1;
71
+ }
72
+
73
+ int integer_callback(void *ctx, long long intVal) {
74
+ set_value(ctx, LONG2NUM(intVal));
75
+ return 1;
76
+ }
77
+
78
+ int double_callback(void *ctx, double doubleVal) {
79
+ set_value(ctx, rb_float_new(doubleVal));
80
+ return 1;
81
+ }
82
+
83
+ int number_callback(void *ctx, const char *numberVal, size_t numberLen) {
84
+ char *buf = (char *)malloc(numberLen+1);
85
+ buf[numberLen] = 0;
86
+ memcpy(buf, numberVal, numberLen);
87
+ if (memchr(buf, '.', numberLen) ||
88
+ memchr(buf, 'e', numberLen) ||
89
+ memchr(buf, 'E', numberLen)) {
90
+ set_value(ctx, rb_float_new(strtod(buf, NULL)));
91
+ } else {
92
+ set_value(ctx, rb_cstr2inum(buf, 10));
93
+ }
94
+ free(buf);
95
+ return 1;
96
+ }
97
+
98
+ int string_callback(void *ctx, const unsigned char *stringVal, size_t stringLen) {
99
+ VALUE str = rb_str_new((const char *)stringVal, stringLen);
100
+ #ifdef HAVE_RUBY_ENCODING_H
101
+ rb_encoding *default_internal_enc = rb_default_internal_encoding();
102
+ rb_enc_associate(str, utf8Encoding);
103
+ if (default_internal_enc) {
104
+ str = rb_str_export_to_enc(str, default_internal_enc);
105
+ }
106
+ #endif
107
+ set_value(ctx,str);
108
+ return 1;
109
+ }
110
+
111
+ int start_map_callback(void *ctx) {
112
+ start_object(ctx,rb_hash_new());
113
+ return 1;
114
+ }
115
+
116
+ int map_key_callback(void *ctx, const unsigned char *stringVal, size_t stringLen) {
117
+ VALUE key;
118
+ #ifdef HAVE_RUBY_ENCODING_H
119
+ rb_encoding *default_internal_enc;
120
+ #endif
121
+
122
+ if ( ((CTX *)ctx)->symbolizeKeys ) {
123
+ #ifdef HAVE_RUBY_ENCODING_H
124
+ ID id = rb_intern3((const char *)stringVal, stringLen, utf8Encoding);
125
+ key = ID2SYM(id);
126
+ #else
127
+ VALUE str = rb_str_new((const char *)stringVal, stringLen);
128
+ key = rb_str_intern(str);
129
+ #endif
130
+ } else {
131
+ key = rb_str_new((const char *)stringVal, stringLen);
132
+ #ifdef HAVE_RUBY_ENCODING_H
133
+ default_internal_enc = rb_default_internal_encoding();
134
+ rb_enc_associate(key, utf8Encoding);
135
+ if (default_internal_enc) {
136
+ key = rb_str_export_to_enc(key, default_internal_enc);
137
+ }
138
+ #endif
139
+ }
140
+ set_key(ctx, key);
141
+ return 1;
142
+ }
143
+
144
+ int end_map_callback(void *ctx) {
145
+ end_object(ctx);
146
+ return 1;
147
+ }
148
+
149
+ int start_array_callback(void *ctx) {
150
+ start_object(ctx,rb_ary_new());
151
+ return 1;
152
+ }
153
+
154
+ int end_array_callback(void *ctx) {
155
+ end_object(ctx);
156
+ return 1;
157
+ }
158
+
159
+ static yajl_callbacks callbacks = {
160
+ null_callback,
161
+ boolean_callback,
162
+ integer_callback,
163
+ double_callback,
164
+ number_callback,
165
+ string_callback,
166
+ start_map_callback,
167
+ map_key_callback,
168
+ end_map_callback,
169
+ start_array_callback,
170
+ end_array_callback,
171
+ };
172
+
173
+ int get_opts_key(VALUE self, const char *key) {
174
+ VALUE opts = rb_iv_get(self, "@opts");
175
+ if (TYPE(opts) != T_HASH) {
176
+ rb_raise(rb_eTypeError, "opts is not a valid hash");
177
+ }
178
+ return rb_hash_aref(opts, ID2SYM(rb_intern(key))) == Qtrue;
179
+ }
180
+
181
+ static VALUE mParser_do_yajl_parse(VALUE self, VALUE str, VALUE yajl_opts) {
182
+ yajl_handle hand;
183
+ yajl_status stat;
184
+ unsigned char *err;
185
+ volatile CTX ctx;
186
+
187
+ rb_ivar_set(self, rb_intern("key"), Qnil);
188
+ rb_ivar_set(self, rb_intern("stack"), rb_ary_new());
189
+ rb_ivar_set(self, rb_intern("key_stack"), rb_ary_new());
190
+
191
+ ctx.self = self;
192
+ ctx.symbolizeKeys = get_opts_key(self, "symbolize_keys");
193
+ ctx.uniqueKeyChecking = get_opts_key(self, "unique_key_checking");
194
+
195
+ hand = yajl_alloc(&callbacks, NULL, (void *)&ctx);
196
+
197
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_comments"))) == Qtrue) {
198
+ yajl_config(hand, yajl_allow_comments, 1);
199
+ }
200
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_dont_validate_strings"))) == Qtrue) {
201
+ yajl_config(hand, yajl_dont_validate_strings, 1);
202
+ }
203
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_trailing_garbage"))) == Qtrue) {
204
+ yajl_config(hand, yajl_allow_trailing_garbage, 1);
205
+ }
206
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_multiple_values"))) == Qtrue) {
207
+ yajl_config(hand, yajl_allow_multiple_values, 1);
208
+ }
209
+ if (rb_hash_aref(yajl_opts, ID2SYM(rb_intern("yajl_allow_partial_values"))) == Qtrue) {
210
+ yajl_config(hand, yajl_allow_partial_values, 1);
211
+ }
212
+
213
+ if ((stat = yajl_parse(hand, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str))) != yajl_status_ok) {
214
+ err = yajl_get_error(hand, 1, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
215
+ goto raise;
216
+ }
217
+ if ((stat = yajl_complete_parse(hand)) != yajl_status_ok) {
218
+ err = yajl_get_error(hand, 1, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
219
+ goto raise;
220
+ }
221
+ yajl_free(hand);
222
+ return rb_ary_pop(rb_ivar_get(self, rb_intern("stack")));
223
+
224
+ raise:
225
+ if (hand) {
226
+ yajl_free(hand);
227
+ }
228
+ rb_raise(cParseError, "%s", err);
229
+ }
230
+
231
+ void Init_parser() {
232
+ mFFI_Yajl = rb_define_module("FFI_Yajl");
233
+ cParseError = rb_define_class_under(mFFI_Yajl, "ParseError", rb_eStandardError);
234
+ mExt = rb_define_module_under(mFFI_Yajl, "Ext");
235
+ mParser = rb_define_module_under(mExt, "Parser");
236
+ rb_define_method(mParser, "do_yajl_parse", mParser_do_yajl_parse, 2);
237
+ #ifdef HAVE_RUBY_ENCODING_H
238
+ utf8Encoding = rb_utf8_encoding();
239
+ #endif
240
+ }
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2011 Brian Lopez - http://github.com/brianmario
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ # Portions Originally Copyright (c) 2008-2011 Brian Lopez - http://github.com/brianmario
2
+ # See MIT-LICENSE
3
+
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "stringio" unless defined?(StringIO)
7
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE !~ /jruby/
8
+ begin
9
+ require "yajl"
10
+ rescue LoadError
11
+ puts "INFO: yajl-ruby not installed"
12
+ end
13
+ else
14
+ puts "INFO: skipping yajl-ruby on jruby"
15
+ end
16
+ require_relative "../../ffi_yajl"
17
+ begin
18
+ require "json" unless defined?(JSON)
19
+ rescue LoadError
20
+ puts "INFO: json gem not installed"
21
+ end
22
+ begin
23
+ require "oj"
24
+ rescue LoadError
25
+ puts "INFO: oj gem not installed"
26
+ end
27
+
28
+ module FFI_Yajl
29
+ class Benchmark
30
+ class Encode
31
+ def run
32
+ # filename = ARGV[0] || 'benchmark/subjects/ohai.json'
33
+ filename = File.expand_path(File.join(File.dirname(__FILE__), "subjects", "ohai.json"))
34
+ hash = File.open(filename, "rb") { |f| FFI_Yajl::Parser.parse(f.read) }
35
+
36
+ times = ARGV[1] ? ARGV[1].to_i : 1000
37
+ puts "Starting benchmark encoding #{filename} #{times} times\n\n"
38
+ ::Benchmark.bmbm do |x|
39
+ x.report("FFI_Yajl::Encoder.encode (to a String)") do
40
+ times.times { FFI_Yajl::Encoder.encode(hash) }
41
+ end
42
+
43
+ ffi_string_encoder = FFI_Yajl::Encoder.new
44
+ x.report("FFI_Yajl::Encoder#encode (to a String)") do
45
+ times.times { ffi_string_encoder.encode(hash) }
46
+ end
47
+
48
+ if defined?(Oj)
49
+ x.report("Oj.dump (to a String)") do
50
+ times.times { Oj.dump(hash) }
51
+ end
52
+ end
53
+
54
+ if defined?(Yajl::Encoder)
55
+ x.report("Yajl::Encoder.encode (to a String)") do
56
+ times.times { Yajl::Encoder.encode(hash) }
57
+ end
58
+
59
+ io_encoder = Yajl::Encoder.new
60
+ x.report("Yajl::Encoder#encode (to an IO)") do
61
+ times.times { io_encoder.encode(hash, StringIO.new) }
62
+ end
63
+
64
+ string_encoder = Yajl::Encoder.new
65
+ x.report("Yajl::Encoder#encode (to a String)") do
66
+ times.times { string_encoder.encode(hash) }
67
+ end
68
+ end
69
+
70
+ if defined?(JSON)
71
+ x.report("JSON.generate") do
72
+ times.times { JSON.generate(hash) }
73
+ end
74
+ x.report("JSON.fast_generate") do
75
+ times.times { JSON.fast_generate(hash) }
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,42 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/..")
2
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
3
+
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "yajl"
7
+ require "stringio" unless defined?(StringIO)
8
+ begin
9
+ require "json" unless defined?(JSON)
10
+ rescue LoadError
11
+ end
12
+
13
+ times = ARGV[0] ? ARGV[0].to_i : 1000
14
+ filename = "benchmark/subjects/ohai.json"
15
+ json = File.new(filename, "r")
16
+ hash = Yajl::Parser.new.parse(json)
17
+ json.close
18
+
19
+ puts "Starting benchmark encoding #{filename} #{times} times\n\n"
20
+ Benchmark.bmbm do |x|
21
+ encoder = Yajl::Encoder.new
22
+ x.report do
23
+ puts "Yajl::Encoder#encode"
24
+ times.times do
25
+ encoder.encode(hash, StringIO.new)
26
+ end
27
+ end
28
+ if defined?(JSON)
29
+ x.report do
30
+ puts "JSON's #to_json"
31
+ times.times do
32
+ JSON.generate(hash)
33
+ end
34
+ end
35
+ end
36
+ x.report do
37
+ puts "Marshal.dump"
38
+ times.times do
39
+ Marshal.dump(hash)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/..")
2
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
3
+
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "yajl"
7
+ begin
8
+ require "json" unless defined?(JSON)
9
+ rescue LoadError
10
+ end
11
+ require "yaml" unless defined?(YAML)
12
+
13
+ # JSON Section
14
+ filename = "benchmark/subjects/ohai.json"
15
+ json = File.new(filename, "r")
16
+ hash = Yajl::Parser.new.parse(json)
17
+ json.close
18
+
19
+ times = ARGV[0] ? ARGV[0].to_i : 1000
20
+ puts "Starting benchmark encoding #{filename} into JSON #{times} times\n\n"
21
+ Benchmark.bmbm do |x|
22
+ encoder = Yajl::Encoder.new
23
+ x.report do
24
+ puts "Yajl::Encoder#encode"
25
+ times.times { encoder.encode(hash, StringIO.new) }
26
+ end
27
+ if defined?(JSON)
28
+ x.report do
29
+ puts "JSON's #to_json"
30
+ times.times { JSON.generate(hash) }
31
+ end
32
+ end
33
+ end
34
+
35
+ # YAML Section
36
+ filename = "benchmark/subjects/ohai.yml"
37
+ yml = File.new(filename, "r")
38
+ data = YAML.load_stream(yml)
39
+ yml.close
40
+
41
+ puts "Starting benchmark encoding #{filename} into YAML #{times} times\n\n"
42
+ Benchmark.bmbm do |x|
43
+ x.report do
44
+ puts "YAML.dump"
45
+ times.times { YAML.dump(data, StringIO.new) }
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ # Portions Originally Copyright (c) 2008-2011 Brian Lopez - http://github.com/brianmario
2
+ # See MIT-LICENSE
3
+
4
+ require "rubygems" unless defined?(Gem)
5
+ require_relative "../../ffi_yajl"
6
+ begin
7
+ require "perftools"
8
+ rescue LoadError
9
+ puts "INFO: perftools.rb gem not installed"
10
+ end
11
+
12
+ ENV["CPUPROFILE_FREQUENCY"] = "4000"
13
+
14
+ module FFI_Yajl
15
+ class Benchmark
16
+ class EncodeProfile
17
+ def run
18
+ return unless defined?(PerfTools)
19
+
20
+ filename = File.expand_path(File.join(File.dirname(__FILE__), "subjects", "ohai.json"))
21
+ hash = File.open(filename, "rb") { |f| FFI_Yajl::Parser.parse(f.read) }
22
+
23
+ times = 1000
24
+ puts "Starting profiling encoding #{filename} #{times} times\n\n"
25
+
26
+ ffi_string_encoder = FFI_Yajl::Encoder.new
27
+ PerfTools::CpuProfiler.start("/tmp/ffi_yajl_encode_profile.out") do
28
+ times.times { ffi_string_encoder.encode(hash) }
29
+ end
30
+ system("pprof.rb --text /tmp/ffi_yajl_encode_profile.out")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/..")
2
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
3
+
4
+ require "rubygems" unless defined?(Gem)
5
+ require "benchmark" unless defined?(Benchmark)
6
+ require "yajl/http_stream"
7
+ require "yajl/gzip"
8
+ require "yajl/deflate"
9
+ require "yajl/bzip2" unless defined?(Bzip2)
10
+ require "json" unless defined?(JSON)
11
+ require "uri" unless defined?(URI)
12
+ require "net/http" unless defined?(Net::HTTP)
13
+
14
+ uri = URI.parse("http://search.twitter.com/search.json?q=github")
15
+ # uri = URI.parse('http://localhost/yajl-ruby.git/benchmark/subjects/contacts.json')
16
+
17
+ times = ARGV[0] ? ARGV[0].to_i : 1
18
+ puts "Starting benchmark parsing #{uri} #{times} times\n\n"
19
+ Benchmark.bmbm do |x|
20
+ x.report do
21
+ puts "Yajl::HttpStream.get"
22
+ times.times { Yajl::HttpStream.get(uri) }
23
+ end
24
+ x.report do
25
+ puts "JSON.parser"
26
+ times.times { JSON.parse(Net::HTTP.get_response(uri).body, max_nesting: false) }
27
+ end
28
+ end