StringBuilder buffer allocation support in compiler
Vitaly Davidovich
vitalyd at gmail.com
Fri Jun 6 16:21:56 UTC 2014
Sorry, hit Send too early. The first version of sayHello in my previous
email should be:
public static String sayHello(String name, int age) {
StringBuilder sb = new StringBuilder();
return sb.append("Hello ").append(name).append(...) ... .toString();
}
On Fri, Jun 6, 2014 at 12:20 PM, Vitaly Davidovich <vitalyd at gmail.com>
wrote:
> 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/4eebf6f5/attachment.html>
More information about the compiler-dev
mailing list