On Fri, 11 Nov 2022 01:41:15 GMT, Jim Laskey <jlas...@openjdk.org> wrote:

>> Thanks, I think benchmarks like this are useful. The `interpolate()` case is 
>> not something I considered when I made my earlier comment. Please add any 
>> benchmarks to the patch as well, so that performance experiments can be  
>> reliably reproduced.
>> 
>> I think what this benchmark mainly shows is the benefit of carriers in 
>> combination with the instance `interpolate()` method. I expect most custom 
>> string processors will interact with string template instances through the 
>> `fragments()` and `values()` methods, though (I don't think there is an 
>> alternative?). i.e. in the end, we still end up boxing everything into a 
>> couple of lists any ways. `interpolate()` also has another leg up in that it 
>> knows the shape of the template when the string template instance is 
>> constructed, and can use a specialized method handle to do the processing.
>> 
>> If I change the benchmark to rely on the `fragments()` and `values()` 
>> accessors (which I think the majority/all of the custom processor will have 
>> to do), for instance by using `st -> 
>> StringTemplate.interpolate(st.fragments(), st.values())` as a custom 
>> processor, and I tweak `StringTemplateImplFactory::newStringTemplate` to use 
>> `List::copyOf` instead of the stream it uses now ([1]), then the list based 
>> implementation is slightly faster than the carriers based implementation on 
>> my machine:
>> 
>> 
>> Benchmark              Mode  Cnt   Score   Error  Units
>> Carriers.carrier       avgt   15  69.946 � 0.599  ns/op
>> Carriers.carrier_inst  avgt   15  15.014 � 0.106  ns/op
>> Carriers.concat        avgt   15   8.441 � 0.021  ns/op
>> Carriers.format        avgt   15   9.314 � 0.172  ns/op
>> Carriers.lists         avgt   15  61.131 � 0.401  ns/op
>> Carriers.str           avgt   15   8.547 � 0.145  ns/op
>> 
>> 
>> It makes me wonder if carriers are worth it at this stage (hard to say... 
>> performance is usually a long string to pull), or if it's better to go 
>> all-in on custom linkage, which should give custom processors performance 
>> that is comparable with `STR` and `FMT`.
>> 
>> Maybe the instance `interpolate()` method is an important enough use-case to 
>> add carriers though. I can't really say.
>> 
>> I appreciate the fact that carriers will see use in future projects as well, 
>> but at face value, it doesn't seem like they add that much for string 
>> templates (rather, on the contrary in some cases it seems).
>> 
>> [1]: http://cr.openjdk.java.net/~jvernee/bench.diff
>
> Something like a StringProcessorFactory could produce the same structures as 
> as interpolate without the boxing issues.
> 
> There are generally two main types of processors (there are others but they 
> would require specialization anyway). The first type doesn't really care 
> about the construction of the string. It just wants to get the interpolation 
> and work with the result. A JSON processor might fall into that category. 
> 
> The second type wants to transform (MH filter args) the fragments or the 
> values or both and then get an interpolation (and maybe work with that 
> result). This is where the StringProcessorFactory would kick in and automate 
> the process and in the end get similar performance as interpolate. No lists 
> or boxing. A formatter processor might fall into that category. 
> 
> What I think you are really objecting to is the existence of StringTemplate 
> objects. Why not just BSM everything?  The problem is that processors can be 
> swapped out and can have state. So you need a user model where the what 
> object (StringTemplate) is separate from the how object (TemplateProcessor).
> 
> Try working through some examples and it will become clearer.

I guess I'm not sure what you have in mind with `StringProcessorFactory`, but I 
think it's starting to become clearer. I expected it to return a method handle 
that took all the dynamic values as arguments (similar to the callsites return 
by the current BSMs), i.e. it would completely bypass `StringTemplate`, but it 
sounds like it will instead take just a `StringTemplate` instance as argument?

In that case carriers make sense to me, as the accesses to the fragments and 
values would be funneled through the StringTemplate instance, and a 
StringProcessorFactory could generate 'sharp' accesses to those values (rather 
than going through `StringTemplate::fragments()` and 
`StringTemplate::values()`, which would box things into lists any ways).

Thanks

-------------

PR: https://git.openjdk.org/jdk/pull/10889

Reply via email to