RFR(S): 8067471: Use private static final char[0] for empty Strings

Lev Priima lev.priima at oracle.com
Fri Dec 19 00:41:30 UTC 2014


Claes,
Thanks for cool suggestion: 
http://cr.openjdk.java.net/~lpriima/8067471/webrev.01/:
   public java.lang.String();
     Signature: ()V
     flags: ACC_PUBLIC
     LineNumberTable:
       line 137: 0
       line 138: 4
       line 139: 13
     Code:
       stack=2, locals=1, args_size=1
          0: aload_0
          1: invokespecial #1                  // Method 
java/lang/Object."<init>":()V
          4: aload_0
          5: ldc           #2                  // String
          7: getfield      #3                  // Field value:[C
         10: putfield      #3                  // Field value:[C
         13: return
       LineNumberTable:
         line 137: 0
         line 138: 4


Aleksey ,
By naive glance, new constructor thrpt is  bigger(jdk9/dev vs 9b42 in 
attach) on:
     @Benchmark
     public String getNewString() {
         return new String();
     }
Please suggest things to compare . Do we have bigapps-like benchmarks 
which may show regression on this?

On 17.12.2014 21:10, Aleksey Shipilev wrote:
> On 17.12.2014 18:58, Claes Redestad wrote:
>> On 2014-12-17 11:22, Lev Priima wrote:
>>> Please review space optimization in no args String constructor.
>>> Originally, it was already rejected once by suggestion in
>>> http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-May/010300.html
>>> w/o formal justification of pros and contras.  And enhancement was
>>> requested again by Nathan Reynolds.
>>>
>>> Issue: https://bugs.openjdk.java.net/browse/JDK-8067471
>>> Patch: http://cr.openjdk.java.net/~lpriima/8067471/webrev.00/
> I am OK with this change pending we understand the performance impact a
> little better. Please do benchmarks.
>
>
>> Could this have some obscure security implications, such as the ability
>> to lock up some subsystem via retrieving and synchronizing on the shared
>> new String().value? I guess not, for practical purposes.
> This would be an issue if we published String.value directly, but we don't.
>
>> I guess it could also be written:
>>
>>      public String() {
>>          this.value = "".value;
>>      }
>>
>> ... which would saves some byte code and should avoid having to allocate
>> a distinct object for this.
> Oh, I like this trick, given "" is probably already in constant pool for
> some other reason. However, there is an additional dereference. We need
> a targeted nanobenchmark to properly quantify the costs for either variant.
>
> -Aleksey.
>
>

-- 
Best Regards,
Lev

-------------- next part --------------
# JMH 1.3.4 (released 8 days ago)
# VM invoker: /home/lev/Downloads/9b42/bin/java
# VM options: <none>
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.MyBenchmark.getEmptyString

# Run progress: 0.00% complete, ETA 00:00:40
# Fork: 1 of 1
# Warmup Iteration   1: 253275307.131 ops/s
# Warmup Iteration   2: 254095116.567 ops/s
# Warmup Iteration   3: 322126895.612 ops/s
# Warmup Iteration   4: 321922181.662 ops/s
# Warmup Iteration   5: 321528859.382 ops/s
# Warmup Iteration   6: 322129274.055 ops/s
# Warmup Iteration   7: 322634217.486 ops/s
# Warmup Iteration   8: 322257029.256 ops/s
# Warmup Iteration   9: 320773906.394 ops/s
# Warmup Iteration  10: 321561537.863 ops/s
Iteration   1: 322106297.965 ops/s
Iteration   2: 322681896.656 ops/s
Iteration   3: 322132279.365 ops/s
Iteration   4: 322677597.123 ops/s
Iteration   5: 322491471.806 ops/s
Iteration   6: 322040955.231 ops/s
Iteration   7: 322462065.350 ops/s
Iteration   8: 322754257.802 ops/s
Iteration   9: 319050435.010 ops/s
Iteration  10: 322166417.156 ops/s


Result: 322056367.347 ±(99.9%) 1646498.649 ops/s [Average]
  Statistics: (min, avg, max) = (319050435.010, 322056367.347, 322754257.802), stdev = 1089056.912
  Confidence interval (99.9%): [320409868.698, 323702865.996]


# JMH 1.3.4 (released 8 days ago)
# VM invoker: /home/lev/Downloads/9b42/bin/java
# VM options: <none>
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.MyBenchmark.getNewString

# Run progress: 50.00% complete, ETA 00:00:20
# Fork: 1 of 1
# Warmup Iteration   1: 74291443.424 ops/s
# Warmup Iteration   2: 83802467.412 ops/s
# Warmup Iteration   3: 103104138.874 ops/s
# Warmup Iteration   4: 103470664.957 ops/s
# Warmup Iteration   5: 102706809.334 ops/s
# Warmup Iteration   6: 103457900.107 ops/s
# Warmup Iteration   7: 103136090.913 ops/s
# Warmup Iteration   8: 101818117.306 ops/s
# Warmup Iteration   9: 103204890.949 ops/s
# Warmup Iteration  10: 101892885.248 ops/s
Iteration   1: 103815433.249 ops/s
Iteration   2: 102628103.785 ops/s
Iteration   3: 104256153.246 ops/s
Iteration   4: 103840204.572 ops/s
Iteration   5: 104059242.583 ops/s
Iteration   6: 103445534.153 ops/s
Iteration   7: 101184072.111 ops/s
Iteration   8: 102174758.595 ops/s
Iteration   9: 101998940.515 ops/s
Iteration  10: 101669182.081 ops/s


Result: 102907162.489 ±(99.9%) 1676975.032 ops/s [Average]
  Statistics: (min, avg, max) = (101184072.111, 102907162.489, 104256153.246), stdev = 1109215.152
  Confidence interval (99.9%): [101230187.457, 104584137.521]


# Run complete. Total time: 00:00:40

Benchmark                          Mode  Samples          Score         Error  Units
o.s.MyBenchmark.getEmptyString    thrpt       10  322056367.347 ± 1646498.649  ops/s
o.s.MyBenchmark.getNewString      thrpt       10  102907162.489 ± 1676975.032  ops/s
-------------- next part --------------
# JMH 1.3.4 (released 8 days ago)
# VM invoker: /home/lev/code/jdk9/dev/build/linux-x86_64-normal-server-release/jdk/bin/java
# VM options: <none>
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.MyBenchmark.getEmptyString

# Run progress: 0.00% complete, ETA 00:00:40
# Fork: 1 of 1
# Warmup Iteration   1: 252880622.163 ops/s
# Warmup Iteration   2: 253543197.037 ops/s
# Warmup Iteration   3: 322030995.381 ops/s
# Warmup Iteration   4: 322037676.959 ops/s
# Warmup Iteration   5: 322019513.020 ops/s
# Warmup Iteration   6: 321444240.836 ops/s
# Warmup Iteration   7: 322124903.148 ops/s
# Warmup Iteration   8: 322300309.941 ops/s
# Warmup Iteration   9: 322207740.544 ops/s
# Warmup Iteration  10: 322228120.576 ops/s
Iteration   1: 322157282.432 ops/s
Iteration   2: 322760503.442 ops/s
Iteration   3: 322138077.016 ops/s
Iteration   4: 322033221.327 ops/s
Iteration   5: 322614522.040 ops/s
Iteration   6: 321949673.639 ops/s
Iteration   7: 322208486.679 ops/s
Iteration   8: 322728645.401 ops/s
Iteration   9: 322701742.545 ops/s
Iteration  10: 319860751.531 ops/s


Result: 322115290.605 ±(99.9%) 1286188.946 ops/s [Average]
  Statistics: (min, avg, max) = (319860751.531, 322115290.605, 322760503.442), stdev = 850734.352
  Confidence interval (99.9%): [320829101.659, 323401479.551]


# JMH 1.3.4 (released 8 days ago)
# VM invoker: /home/lev/code/jdk9/dev/build/linux-x86_64-normal-server-release/jdk/bin/java
# VM options: <none>
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.sample.MyBenchmark.getNewString

# Run progress: 50.00% complete, ETA 00:00:20
# Fork: 1 of 1
# Warmup Iteration   1: 95384786.922 ops/s
# Warmup Iteration   2: 114919375.499 ops/s
# Warmup Iteration   3: 156152523.678 ops/s
# Warmup Iteration   4: 156669076.485 ops/s
# Warmup Iteration   5: 154457001.474 ops/s
# Warmup Iteration   6: 155779532.552 ops/s
# Warmup Iteration   7: 155481156.649 ops/s
# Warmup Iteration   8: 156513950.903 ops/s
# Warmup Iteration   9: 157269815.082 ops/s
# Warmup Iteration  10: 155383469.586 ops/s
Iteration   1: 155354136.440 ops/s
Iteration   2: 157690383.417 ops/s
Iteration   3: 156088525.012 ops/s
Iteration   4: 155434125.275 ops/s
Iteration   5: 155756683.197 ops/s
Iteration   6: 156746735.419 ops/s
Iteration   7: 172867452.406 ops/s
Iteration   8: 175637166.777 ops/s
Iteration   9: 176995419.709 ops/s
Iteration  10: 175064276.835 ops/s


Result: 163763490.449 ±(99.9%) 14914652.052 ops/s [Average]
  Statistics: (min, avg, max) = (155354136.440, 163763490.449, 176995419.709), stdev = 9865118.875
  Confidence interval (99.9%): [148848838.397, 178678142.500]


# Run complete. Total time: 00:00:40

Benchmark                          Mode  Samples          Score          Error  Units
o.s.MyBenchmark.getEmptyString    thrpt       10  322115290.605 ±  1286188.946  ops/s
o.s.MyBenchmark.getNewString      thrpt       10  163763490.449 ± 14914652.052  ops/s


More information about the core-libs-dev mailing list