summaryrefslogtreecommitdiff
path: root/java/src/json/ext/Parser.rl
diff options
context:
space:
mode:
authorBen Browning <bbrownin@redhat.com>2014-12-16 10:12:10 -0500
committerBen Browning <bbrownin@redhat.com>2014-12-16 10:12:10 -0500
commiteaac48419d196e909fcdf526c4e3dbec2cc3d19b (patch)
tree1f851077f62e776de524e731a3b092f4b5b6a782 /java/src/json/ext/Parser.rl
parent17fe8e72f484e65e0c36670946934d1f8696e37b (diff)
downloadjson-eaac48419d196e909fcdf526c4e3dbec2cc3d19b.tar.gz
Improve JRuby perf. by removing source of multithreaded contention
The RuntimeInfo.forRuntime method synchronizes all invocations and ParserSession#parseString was calling this many times when parsing large JSON strings. Thus, when running in a heavily multithreaded environment, threads were spending a large portion of their time waiting on that synchronization instead of doing work parsing the JSON. This fix simply passes in the RuntimeInfo object to the ParserSession when it's instantiated, since the RuntimeInfo is already known and we've already incurred the synchronization cost at that time. Using the test script at https://gist.github.com/bbrowning/0b89580b03a5f19e7a9f, I get the following results before and after this fix on my machine: Before: $ jruby ~/tmp/json_contention.rb 337.920000 0.570000 338.490000 ( 57.955000) After: $ jruby ~/tmp/json_contention.rb 326.400000 0.580000 326.980000 ( 43.084000) That's a 25% reduction in processing time for parsing the same JSON on my quad core machine. I'd expect an even higher percentage improvement on a machine with more CPUs.
Diffstat (limited to 'java/src/json/ext/Parser.rl')
-rw-r--r--java/src/json/ext/Parser.rl9
1 files changed, 5 insertions, 4 deletions
diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl
index 7dcdd2e..6d65963 100644
--- a/java/src/json/ext/Parser.rl
+++ b/java/src/json/ext/Parser.rl
@@ -246,7 +246,7 @@ public class Parser extends RubyObject {
*/
@JRubyMethod
public IRubyObject parse(ThreadContext context) {
- return new ParserSession(this, context).parse();
+ return new ParserSession(this, context, info).parse();
}
/**
@@ -302,6 +302,7 @@ public class Parser extends RubyObject {
private static class ParserSession {
private final Parser parser;
private final ThreadContext context;
+ private final RuntimeInfo info;
private final ByteList byteList;
private final ByteList view;
private final byte[] data;
@@ -313,9 +314,10 @@ public class Parser extends RubyObject {
// no idea about the origins of this value, ask Flori ;)
private static final int EVIL = 0x666;
- private ParserSession(Parser parser, ThreadContext context) {
+ private ParserSession(Parser parser, ThreadContext context, RuntimeInfo info) {
this.parser = parser;
this.context = context;
+ this.info = info;
this.byteList = parser.checkAndGetSource().getByteList();
this.data = byteList.unsafeBytes();
this.view = new ByteList(data, false);
@@ -646,8 +648,7 @@ public class Parser extends RubyObject {
}
}
- if (cs >= JSON_string_first_final && result != null) {
- RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
+ if (cs >= JSON_string_first_final && result != null) {
if (info.encodingsSupported() && result instanceof RubyString) {
((RubyString)result).force_encoding(context, info.utf8.get());
}