<i18n dev> RFR: JDK-8285932 Implementation of JEP-430 String Templates (Preview) [v17]

Jorn Vernee jvernee at openjdk.org
Fri Nov 11 02:43:46 UTC 2022


On Fri, 11 Nov 2022 01:41:15 GMT, Jim Laskey <jlaskey at 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


More information about the i18n-dev mailing list