StringBuilder buffer allocation support in compiler
Vitaly Davidovich
vitalyd at gmail.com
Fri Jun 6 16:20:49 UTC 2014
I don't see how it's in sync; you're testing appending in a loop (with
non-constant trip count, at least unless JIT completely devirtualizes and
inlines everything). I thought the topic of this thread was difference in
performance between effectively:
public static String sayHello(String name, int age) {
//return "Hello " + name + ", this is your " + age + "th birthday";
StringBuilder sb = new StringBuilder(<proper_size>);
return sb.append("Hello ").append(name).append(...) ... .toString();
}
vs
public static String sayHello(String name, int age) {
StringBuilder sb = new StringBuilder(<proper_size>);
return sb.append("Hello ").append(name).append(...) ... .toString();
}
There's no loop here and each invocation of this is a separate
StringBuilder instance, so even if you were to call sayHello() from a loop,
the semantics are different from your benchmark.
On Fri, Jun 6, 2014 at 12:07 PM, Laszlo Hornyak <laszlo.hornyak at gmail.com>
wrote:
> I think that is in sync with the subject of this email thread.
>
>
> On Thu, Jun 5, 2014 at 11:01 PM, Vitaly Davidovich <vitalyd at gmail.com>
> wrote:
>
>> I think your benchmark is testing something else though, which is cost of
>> resizing during appends.
>>
>> To test the issue at hand, try writing two methods, one which does string
>> appends manually to a pre allocated SB of the right size (which is what you
>> want javac to do) and one that does the string concat.
>>
>> Sent from my phone
>> On Jun 5, 2014 4:39 PM, "Laszlo Hornyak" <laszlo.hornyak at gmail.com>
>> wrote:
>>
>>> Hi Vitaly,
>>>
>>> I tested with server VM and the test code has some warmup so that the
>>> JIT should have enough time to kick in, but I will check stringopts if it
>>> should do some relevant optimization.
>>>
>>>
>>>
>>> On Thu, Jun 5, 2014 at 9:43 PM, Vitaly Davidovich <vitalyd at gmail.com>
>>> wrote:
>>>
>>>> Hi Laszlo,
>>>>
>>>> I believe server jit compiler has an optimization pass that will
>>>> attempt at fusing this type of pattern into one string allocation -- see
>>>> src/share/vm/opto/stringopts.[h|c]pp in the sources. Have you tried
>>>> benchmarking this after jit compiler gets a crack at it?
>>>>
>>>>
>>>> On Thu, Jun 5, 2014 at 3:27 PM, Laszlo Hornyak <
>>>> laszlo.hornyak at gmail.com> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> Given this sample code
>>>>>
>>>>> public static String sayHello(String name, int age) {
>>>>> return "Hello " + name + ", this is your " + age + "th
>>>>> birthday";
>>>>> }
>>>>>
>>>>> The compiler will generate this bytecode:
>>>>> 0: new #11 // class
>>>>> java/lang/StringBuilder
>>>>> 3: dup
>>>>> 4: invokespecial #12 // Method
>>>>> java/lang/StringBuilder."<init>":()V
>>>>> 7: ldc #19 // String Hello
>>>>> 9: invokevirtual #15 // Method
>>>>> java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
>>>>> 12: aload_0
>>>>> 13: invokevirtual #15 // Method
>>>>> java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
>>>>> 16: ldc #20 // String , this is your
>>>>> 18: invokevirtual #15 // Method
>>>>> java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
>>>>> 21: iload_1
>>>>> 22: invokevirtual #13 // Method
>>>>> java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
>>>>> 25: ldc #21 // String th birthday
>>>>> 27: invokevirtual #15 // Method
>>>>> java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
>>>>> 30: invokevirtual #17 // Method
>>>>> java/lang/StringBuilder.toString:()Ljava/lang/String;
>>>>> 33: areturn
>>>>>
>>>>> The most interesting line is:
>>>>> 4: invokespecial #12 // Method
>>>>> java/lang/StringBuilder."<init>":()V
>>>>>
>>>>>
>>>>> Since all the string literals are given for the compiler, it could
>>>>> give an estimation on the required buffer size to the StringBuilder
>>>>> constructor. In this example the string literals already take 32
>>>>> characters, plus a string representation of an integer takes up to 12
>>>>> characters. The String size is 0 to Integer.MAX_VALUE, but 16 might be a
>>>>> good default. In this case a constructor call could be generated to
>>>>> allocate a buffer with 50 characters and some (possibly all) buffer
>>>>> re-allocation could be saved in the subsequent append calls.
>>>>> The performance gain seems to be significant since the subsequent
>>>>> buffer allocations can take up to 30-40 percent of the execution time.
>>>>> Is there a specific reason for the java compiler not to support
>>>>> pre-allocation of StringBuilder buffer based on string literals and
>>>>> parameters?
>>>>>
>>>>> Thank you,
>>>>> Laszlo
>>>>>
>>>>>
>>>>> --
>>>>>
>>>>> EOF
>>>>>
>>>>
>>>>
>>>
>>>
>>> --
>>>
>>> EOF
>>>
>>
>
>
> --
>
> EOF
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20140606/4b0097bf/attachment-0001.html>
More information about the compiler-dev
mailing list