RFR: JDK-8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
Peter Levart
peter.levart at gmail.com
Wed May 30 21:16:42 UTC 2018
I thought there would be some hint from Alan about which of the two
paths we should take for more refinement.
The Tony's:
http://cr.openjdk.java.net/~tonyp/8202788/webrev.1/
Or the Alan's with my mods:
http://cr.openjdk.java.net/~plevart/jdk-dev/DBBCache_Cleanup/webrev.02/
Regards, Peter
On 05/30/18 22:46, Tony Printezis wrote:
> Hi all,
>
> Any more thoughts on this? (with apologies for the ping)
>
> Tony
>
>
> —————
> Tony Printezis | @TonyPrintezis | tprintezis at twitter.com
> <mailto:tprintezis at twitter.com>
>
>
> On May 18, 2018 at 3:58:57 PM, Tony Printezis (tprintezis at twitter.com
> <mailto:tprintezis at twitter.com>) wrote:
>
>> Hi again,
>>
>> Stylistically, I strongly prefer this version over the previous one
>> (the one with the doubly-linked list of JdkThreadLocal entries) you
>> had posted. This one is a lot cleaner.
>>
>> A few suggestions:
>>
>> * I’m not crazy about the fact that the users have to override
>> calculateInitialValue() instead of initialValue() as it will be a bit
>> error-prone. If they accidentally override initialValue() then the
>> per-thread registering is not going to happen. Maybe I’m overthinking
>> this. One way to get round this is for each JdkThreadLocal instance
>> to delegate calls to get(), set(), and remove() to a private
>> ThreadLocal instance, which can in turn delegate initialValue() to
>> the outer instance. (Hope this makes sense?) I did a quick prototype
>> of this and it seems to work, but I didn’t heavily test it.
>>
>> * I would prefer if the method users override actually took the
>> thread-local value as a parameter, i.e., protected void
>> threadTerminated(T value). This is very easy to add:
>>
>> protected void threadTerminated(T value) {
>> }
>>
>> private void threadTerminated() {
>> threadTerminated(get());
>> }
>>
>> and I think it will be easier to use, as most uses will probably need
>> to do get() anyway.
>>
>> Tony
>>
>> —————
>> Tony Printezis | @TonyPrintezis | tprintezis at twitter.com
>> <mailto:tprintezis at twitter.com>
>>
>>
>> On May 18, 2018 at 4:23:19 AM, Peter Levart (peter.levart at gmail.com
>> <mailto:peter.levart at gmail.com>) wrote:
>>
>>> It's good to have alternative implementations on the table. Here's
>>> another variant that is space neutral for threads that don't use
>>> JdkThreadLocal, but also scales to many JdkThreadLocal instances:
>>>
>>> http://cr.openjdk.java.net/~plevart/jdk-dev/DBBCache_Cleanup/webrev.02/
>>>
>>> Now we only need an arbiter to decide which one! :-)
>>>
>>> Regards, Peter
>>>
>>> On 05/17/18 22:39, Peter Levart wrote:
>>>> Hi Tony,
>>>>
>>>> If we anticipate only small number of JdkThreadLocal(s) (there will
>>>> be only one for the start) then this is a plausible solution. Then
>>>> perhaps this limitation should be written somewhere in the
>>>> JdkThreadLocal javadoc so that one day somebody will not be tempted
>>>> to use JdkThreadLocal(s) en masse. Let's say there will be a few
>>>> more JdkThreadLocal(s) in the future. Are we willing to pay for a
>>>> few lookups into a ThreadLocalMap at each and every thread's exit
>>>> even though such thread did not register a mapping for any
>>>> JdkThreadLocal? Is an additional reference field in each and every
>>>> ThreadLocalMap (one per Thread that uses thread locals) a bigger
>>>> price to pay? I don't know. Will let others comment on this.
>>>>
>>>> Otherwise the code looks good. Just a couple of observations:
>>>>
>>>> Since private static method JdkThreadLocal.add is only called from
>>>> JdkThreadLocal constructor with just constructed instance (this),
>>>> there's no possibility for it to be called twice or more times with
>>>> the same instance. The check for duplicates could go away then, right?
>>>>
>>>> You keep an array of Entry objects which are just wrappers for
>>>> JdkThreadLocal objects. Are you already planning for Entry to
>>>> become a WeakReference? Otherwise you could just keep
>>>> JdkThreadLocal objects in the array directly.
>>>>
>>>> Regards, Peter
>>>>
>>>> On 05/17/18 20:25, Tony Printezis wrote:
>>>>> Hi all,
>>>>>
>>>>> I have a new version of the code for your consideration:
>>>>>
>>>>> http://cr.openjdk.java.net/~tonyp/8202788/webrev.1/
>>>>> <http://cr.openjdk.java.net/%7Etonyp/8202788/webrev.1/>
>>>>>
>>>>> I basically combined our two approaches. The usage is as Alan had
>>>>> proposed it: Users have to use JdkThreadLocal (which is only
>>>>> available within java.base) and override threadTerminated().
>>>>> However, I keep track of JdkThreadLocal instances globally (as I
>>>>> did before) and not per-thread. This way we don’t need to add any
>>>>> unnecessary complexity to ThreadLocalMap.
>>>>>
>>>>> Currently, I don’t allow entries to be purged if the
>>>>> JdkThreadLocal instance becomes otherwise unreachable. I can
>>>>> easily add that functionality if needed (I can use WeakReferences
>>>>> for that). However, for the uses we’re considering, is it really
>>>>> necessary?
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> Tony
>>>>>
>>>>>
>>>>> —————
>>>>> Tony Printezis | @TonyPrintezis | tprintezis at twitter.com
>>>>> <mailto:tprintezis at twitter.com>
>>>>>
>>>>>
>>>>> On May 14, 2018 at 12:40:28 PM, Tony Printezis
>>>>> (tprintezis at twitter.com <mailto:tprintezis at twitter.com>) wrote:
>>>>>
>>>>>> Peter,
>>>>>>
>>>>>> In my proposal, you can register the exit hook in the ThreadLocal
>>>>>> c’tor, so it’s almost as nice as Alan’s in that respect (and it
>>>>>> doesn't require an extra field per ThreadLocal plus two extra
>>>>>> fields per JdkEntry). :-)
>>>>>>
>>>>>> But, I do like the addition of the JdkEntry list to avoid
>>>>>> unnecessarily iterating over all the map entries (which was my
>>>>>> main concern with Alan’s original webrev). I’ll be totally happy
>>>>>> with a version of this.
>>>>>>
>>>>>> Tony
>>>>>>
>>>>>>
>>>>>> —————
>>>>>> Tony Printezis | @TonyPrintezis | tprintezis at twitter.com
>>>>>> <mailto:tprintezis at twitter.com>
>>>>>>
>>>>>>
>>>>>> On May 12, 2018 at 6:44:08 AM, Peter Levart
>>>>>> (peter.levart at gmail.com <mailto:peter.levart at gmail.com>) wrote:
>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 05/11/18 16:13, Alan Bateman wrote:
>>>>>>>> On 08/05/2018 16:07, Tony Printezis wrote:
>>>>>>>>> Hi all,
>>>>>>>>>
>>>>>>>>> Following the discussion on this a few weeks ago, here’s the
>>>>>>>>> first version
>>>>>>>>> of the change:
>>>>>>>>>
>>>>>>>>> http://cr.openjdk.java.net/~tonyp/8202788/webrev.0/
>>>>>>>>>
>>>>>>>>> I think the consensus was that it’d be easier if the exit
>>>>>>>>> hooks were only
>>>>>>>>> available within java.base. Is it enough that I added the
>>>>>>>>> functionality to
>>>>>>>>> the jdk.internal.misc package? (And is jdk.internal.misc the
>>>>>>>>> best place for
>>>>>>>>> this?)
>>>>>>>>>
>>>>>>>>> I’ll also add a test for the new functionality. But let’s
>>>>>>>>> first come up
>>>>>>>>> with an approach that everyone is happy with. :-)
>>>>>>>>>
>>>>>>>> Peter's approach in early April was clean (and we should come
>>>>>>>> to the getIfPresent discussion) but it adds a field to Thread
>>>>>>>> for the callback list. If I read your approach correctly, you
>>>>>>>> are avoiding that by maintaining an array of hooks in
>>>>>>>> ThreadLocalExitHooks.
>>>>>>>>
>>>>>>>> Another approach to try is a java.base-internal ThreadLocal
>>>>>>>> that defines a method to be invoked when a thread terminates.
>>>>>>>> Something like the following:
>>>>>>>> http://cr.openjdk.java.net/~alanb/8202788/webrev/index.html
>>>>>>>>
>>>>>>>> -Alan
>>>>>>>
>>>>>>> From the API perspective, Alan's suggestion is the most
>>>>>>> attractive one as it puts the method to where it belongs - into
>>>>>>> the ThreadLocal instance. But the implementation could be
>>>>>>> improved a bit. I don't like the necessity to iterate over all
>>>>>>> ThreadLocal(s) to filter out JdkThreadLocal(s). There might be a
>>>>>>> situation where there's plenty of ThreadLocal(s) registered per
>>>>>>> exiting thread which would produce a spike in CPU processing at
>>>>>>> thread exit.
>>>>>>>
>>>>>>> The way to avoid this would be to maintain a separate linked
>>>>>>> list of entries that contains just those with JdkThreadLocal(s).
>>>>>>> Like in this modification of Alan's patch, for example:
>>>>>>>
>>>>>>> http://cr.openjdk.java.net/~plevart/jdk-dev/DBBCache_Cleanup/webrev.01/
>>>>>>>
>>>>>>> (Only ThreadLocal class is modified from Alan's patch)
>>>>>>>
>>>>>>> What do you think?
>>>>>>>
>>>>>>>
>>>>>>> Regards, Peter
>>>>>>>
>>>>
>>>
More information about the core-libs-dev
mailing list