Constant_Dynamic first experiences
Claes Redestad
claes.redestad at oracle.com
Tue Jul 3 20:11:14 UTC 2018
Right, it'd be interesting to see the output of
-Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true for the A case. If
there's a lot of non-"success" messages, pre-spinning could be a solution.
(I'd be interested with playing around with the various emission
strategies regardless)
/Claes
On 2018-07-03 21:19, Brian Goetz wrote:
> I suspect the startup regression has to do with spinning the needed lambda forms. We’ve done some work with pre-spinning the ones we know will be needed, and bundling them into the runtime. Obviously this only works if you’re packaging a runtime, but its an option.
>
>
>> On Jul 3, 2018, at 3:13 PM, Ghadi Shayban <gshayban at gmail.com> wrote:
>>
>> Thank you both.
>>
>> For _nested constant aggregates_, I'll try John's leaf+steering suggestion,
>> but that will take a bit more surgery.
>>
>> Re: getting rid of array bytecode boilerplate, I tried a few things in the
>> context of making a _non-constant_ vector.
>>
>> Emission styles:
>> A)
>> push MethodHandle for clojure.lang.RT.vector(Object...)
>> push all elements
>> signature polymorphic call to MH.invoke
>>
>> B)
>> push all elements
>> invokedynamic, with BSM returning a CCS around RT.vector(Object...),
>> adapted for the incoming signature with asType()
>>
>> C) same as B but the CallSite+MH is memoized for arities <= 6 using
>> asCollector()
>>
>> All of these worked but had a slight startup regression, more severe in
>> approach A (~0.65s -> ~0.85s).
>> I'm not sure whether I am using MH combinators properly, or invoke vs
>> invokeExact.
>>
>> Are there any other approaches to try out? I wasn't sure about the List.of
>> bit. Are you suggesting unrolling the target constructor?
>>
>> [1] found this old gem
>> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-April/009661.html
>>
>>
>> On Mon, Jul 2, 2018 at 5:05 PM, John Rose <john.r.rose at oracle.com> wrote:
>>
>>> On Jul 2, 2018, at 1:31 PM, Ghadi Shayban <gshayban at gmail.com> wrote:
>>>
>>>
>>> there are a lot of
>>> _totally constant aggregates_ that get executed once only during clojure
>>> runtime initialization (nearly everything is reified in the clojure
>>> runtime: docstrings, file:line numbers.)
>>>
>>> Is there anything that you would suggest for speeding up the (one-time)
>>> creation of constant aggregates? Or am I best off with aastores then
>>> calling a varargs constructor as we do currently?
>>>
>>>
>>> If you are creating a true constant aggregate, you shouldn't need
>>> to execute any aastores to set up component arrays and/or argument
>>> lists. Instead, use a BSM that takes a varargs of the elements, and
>>> let the BSM execution logic stack those things for you. That should
>>> be about as fast as a one-time run of anewarray/aastore/invokestatic.
>>>
>>> A similar point applies to component tuples or small structs, although
>>> varargs BSMs very naturally encode arrays. As Brian says, they also
>>> naturally encode List.of calls, which are built on top of throw-away array.
>>> Suppose you had a constant k/v pair: You could bind that to a condy
>>> constant, and so for a constant map of N pairs you'd have N+1 condys.
>>> I don't recommend going that far, since CP entries are scarce compared
>>> to bytecodes (limit of 2^16). Instead, for a complex constant aggregate
>>> structure, perhaps with nesting, devise a variadic BSM which takes
>>> all of the leaf data in one argument list, and DTRT to assemble it.
>>> In general you'll need steering tokens mixed with your argument list,
>>> such as argument counts (java.lang.Integer) etc. That gets your
>>> job done in 1 condy (plus a various non-condy tokens or recursive
>>> uses of unrelated condy constants). As a compromise, you could
>>> assemble a variable number of aggregate components into a fixed
>>> number M of List.of constants (which work great with condy, and will
>>> get better in the future). Then a final BSM would assemble the
>>> M lists with ad hoc steering data into you aggregate, for M+1
>>> (<< N+1) condy nodes in the constant pool.
>>>
>>> If you run into performance potholes in BSM execution, please do
>>> let us know; we care about rounding off rough edges in BSMs,
>>> since they are so pervasively used.
>>>
>>> Thank you for the kind words; we do this work so you can develop
>>> cool stuff like Clojure on top of Java and the JVM, and it's encouraging
>>> to know when our mad plans succeed.
>>>
>>> — John
>>>
More information about the amber-dev
mailing list