RFR: 8185005: Improve performance of ThreadMXBean.getThreadInfo(long ids[], int maxDepth)

Daniel D. Daugherty daniel.daugherty at oracle.com
Sat Sep 21 01:11:27 UTC 2019



On 9/20/19 9:07 PM, Daniel D. Daugherty wrote:
> On 9/20/19 7:15 PM, serguei.spitsyn at oracle.com wrote:
>> Hi Dan,
>>
>> Please, find a minor correction below.
>>
>>
>> On 9/20/19 2:59 PM, Daniel D. Daugherty wrote:
>>> Daniil,
>>>
>>> Thanks for sticking with this project through the many versions.
>>> Sorry this review is late...
>>>
>>>
>>> On 9/19/19 8:30 PM, Daniil Titov wrote:
>>>> Hi David and Serguei,
>>>>
>>>> Please review new version of the fix that includes the changes 
>>>> Serguei suggested:
>>>>   1. If racing threads initialize the thread table only one of 
>>>> these threads will populate the table with the threads from the 
>>>> thread list
>>>>   2. The code that adds the thread to the tread table is put inside 
>>>> Threads_lock to ensure that we cannot accidentally add the thread
>>>>       that has just passed the removal point in 
>>>> ThreadsSMRSupport::remove_thread()
>>>>
>>>> The changes are in ThreadTable::lazy_initialize() method only.
>>>>
>>>> Testing:  Mach5 tier1, tier2, tier3, tier4, and tier5 tests 
>>>> successfully passed.
>>>>
>>>> Webrev: https://cr.openjdk.java.net/~dtitov/8185005/webrev.07/
>> . . .
>>> L93: void ThreadTable::lazy_initialize(const ThreadsList *threads) {
>>>         Re: discussion about lazy_initialize() racing with
>>>             ThreadsList::find_JavaThread_from_java_tid()
>>>
>>>         There's a couple of aspects to these two pieces of code racing
>>>         with each other and racing with new thread creation. Racing 
>>> with
>>>         new thread creation is the easy one:
>>>
>>>           If a new thread isn't added to the ThreadTable by
>>>           ThreadsSMRSupport::add_thread() calling 
>>> ThreadTable::add_thread(),
>>>           then the point in the future where someone calls
>>>           find_JavaThread_from_java_tid() will add it to the table 
>>> due to
>>>           the linear search when ThreadTable::find_thread_by_tid()
>>>           returns NULL.
>>>
>>>        As for multi-threads calling 
>>> ThreadsList::find_JavaThread_from_java_tid()
>>>        at the same time which results in multi-threads in 
>>> lazy_initialize()
>>>        at the same time...
>>>
>>>        - ThreadTable creation will be linear due to 
>>> ThreadTableCreate_lock.
>>>          After _is_initialized is set to true, then no more callers to
>>>          lazy_initialize() will be in the "if (!_is_initialized)" 
>>> block.
>>>        - Once the ThreadTable is created, then multi-threads can be
>>>          executing the for-loop to add their ThreadsList entries to
>>>          the ThreadTable.
>>
>> I guess, there is a confusion here.
>> The lines 97-101 were recently added into the latest webrev:
>>
>>   93 void ThreadTable::lazy_initialize(const ThreadsList *threads) {
>>   94   if (!_is_initialized) {
>>   95     {
>>   96       MutexLocker ml(ThreadTableCreate_lock);
>>   97       if (_is_initialized) {
>>   98         // There is no obvious benefits in allowing the thread 
>> table
>>   99         // being concurently populated during the initalization.
>>  100         return;
>>  101       }
>>
>> It prevents multi-threads executing the for-loop to add their
>> ThreadsList entries to the ThreadTable.
>> Instead, these threads may not find the requested threads in the
>> ThreadTable and so, will start linear search in their ThreadsList
>> to add them into the ThreadTable.

I should have read your comment more carefully...

Yes, you are right about the early cut out on L97-100 causing
the for-loop to be skipped by any thread that saw (!_is_initialized)
and was blocked on the ThreadTableCreate_lock.

So my response below is wrong...

Sorry about the noise.

Dan

>
> The ThreadTableCreate_lock is only held from here:
>
>   L95:     {
>   L96:       MutexLocker ml(ThreadTableCreate_lock);
>
> to here:
>
>   L103:       _is_initialized = true;
>   L104:     }
>
> and the for-loop starts here:
>
>   L105:     for (uint i = 0; i < threads->length(); i++) {
>
> so the ThreadTable_Create_lock does not linearize the
> for-loop.
>
> I'm quoting webrev.07... which I believe is the latest.
>
> Dan
>
>
>>
>> . . .
>>> Short version: Thumbs up.
>>>
>>> Longer version: I don't think I've spotted anything other than nits 
>>> here.
>>> Mostly I've just looked for multi-threaded races, proper usage of the
>>> Thread-SMR stuff, and minimal impact in the case where the new
>>> ThreadsTable is never needed.
>>>
>>> Dan
>>>
>>> P.S.
>>> ThreadTable is a bit of misnomer. What you really have here is
>>> a ThreadIdTable, but I'm really late to the code review flow
>>> with that comment...
>>
>> Agreed, ThreadIdTable is better name for this table.
>>
>> Thanks,
>> Serguei
>>
>>
>>>
>>>
>>>> Bug : https://bugs.openjdk.java.net/browse/JDK-8185005
>>>>
>>>> Thank you!
>>>> --Daniil
>>>
>>
>



More information about the serviceability-dev mailing list