Skip to content

Loading…

Cache DecimalFormatSymbols instances to reduce lock contention #1414

Merged
merged 1 commit into from

3 participants

@bbrowning

Constructing new DecimalFormatSymbols instances requires locking, and
in some sample Rails apps this contention was bubbling up as a
bottleneck. So, this change caches DecimalFormatSymbols instances
per-thread just like NumberFormat instances are already cached.

The overall throughput in my test application wasn't much changed
because of ActiveRecord's connection mutex still sitting in this way,
but this does get rid of one source of multi-threaded lock contention.

@bbrowning bbrowning Cache DecimalFormatSymbol instances to reduce lock contention
Constructing new DecimalFormatSymbol instances requires locking, and
in some sample Rails apps this contention was bubbling up as a
bottleneck. So, this change caches DecimalFormatSymbol instances
per-thread just like NumberFormat instances are already cached.

The overall throughput in my test application wasn't much changed
because of ActiveRecord's connection mutex still sitting in this way,
but this does get rid of one source of multi-threaded lock contention.
5d386a8
@headius headius merged commit 716ebbc into jruby:jruby-1_7

1 check failed

Details default The Travis CI build failed
@enebo enebo added this to the JRuby 1.7.11 milestone
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 17, 2014
  1. @bbrowning

    Cache DecimalFormatSymbol instances to reduce lock contention

    bbrowning committed
    Constructing new DecimalFormatSymbol instances requires locking, and
    in some sample Rails apps this contention was bubbling up as a
    bottleneck. So, this change caches DecimalFormatSymbol instances
    per-thread just like NumberFormat instances are already cached.
    
    The overall throughput in my test application wasn't much changed
    because of ActiveRecord's connection mutex still sitting in this way,
    but this does get rid of one source of multi-threaded lock contention.
Showing with 16 additions and 2 deletions.
  1. +16 −2 core/src/main/java/org/jruby/util/Sprintf.java
View
18 core/src/main/java/org/jruby/util/Sprintf.java
@@ -95,6 +95,12 @@
return new HashMap<Locale, NumberFormat>();
}
};
+
+ private static final ThreadLocal<Map<Locale, DecimalFormatSymbols>> LOCALE_DECIMAL_FORMATS = new ThreadLocal<Map<Locale, DecimalFormatSymbols>>() {
+ protected Map<Locale, DecimalFormatSymbols> initialValue() {
+ return new HashMap<Locale, DecimalFormatSymbols>();
+ }
+ };
private static final class Args {
private final Ruby runtime;
@@ -207,8 +213,7 @@ int intValue(IRubyObject obj) {
}
byte getDecimalSeparator() {
- // not saving DFS instance, as it will only be used once (at most) per call
- return (byte)new DecimalFormatSymbols(locale).getDecimalSeparator();
+ return (byte)getDecimalFormat(locale).getDecimalSeparator();
}
} // Args
@@ -1337,6 +1342,15 @@ public static NumberFormat getNumberFormat(Locale locale) {
return format;
}
+ public static DecimalFormatSymbols getDecimalFormat(Locale locale) {
+ DecimalFormatSymbols format = LOCALE_DECIMAL_FORMATS.get().get(locale);
+ if (format == null) {
+ format = new DecimalFormatSymbols(locale);
+ LOCALE_DECIMAL_FORMATS.get().put(locale, format);
+ }
+ return format;
+ }
+
private static void writeExp(ByteList buf, int exponent, byte expChar) {
// Unfortunately, the number of digits in the exponent is
// not clearly defined in Ruby documentation. This is a
Something went wrong with that request. Please try again.