RFR: NMT: Don't record uncommits unconditionally
Stefan Karlsson
stefan.karlsson at oracle.com
Thu Jan 11 15:31:22 UTC 2018
On 2018-01-11 15:15, Zhengyu Gu wrote:
>
>
> On 01/11/2018 08:51 AM, Stefan Karlsson wrote:
>> Hi Zhengyu,
>>
>> I think I found the reason why this uses the Tracker like this:
>>
>> // Tracker is used for guarding 'release' semantics of virtual memory
>> operation, to avoid
>> // the other thread obtains and records the same region that is just
>> 'released' by current
>> // thread but before it can record the operation.
> Ah, Thanks!
>
> But I still want to throw away
> MemTracker::get_virtual_memory_uncommit_tracker() and create Tracker in
> place.
OK. Will you take care of it?
If you want, you can take over this RFE:
https://bugs.openjdk.java.net/browse/JDK-8194926
Here's the updated ZGC patch.
http://cr.openjdk.java.net/~stefank/zgc/zNMTBugFix/webrev.02
The move of the nmt_uncommit call is not strictly necessary, because
both the "unmap" and the "alloc" of the physical memory is protected by
the same lock, but it makes the the code a bit more future proof.
Thanks,
StefanK
>
> -Zhengyu
>
>>
>> So, my proposed patch would undo that. I'll throw away that upstream
>> patch and only create a proper ZGC change.
>>
>> Thanks,
>> StefanK
>>
>> On 2018-01-11 14:38, Zhengyu Gu wrote:
>>>
>>>
>>> On 01/11/2018 08:33 AM, Zhengyu Gu wrote:
>>>> On 01/11/2018 05:28 AM, Stefan Karlsson wrote:
>>>>> If we decide that the below change is valid and an improvement,
>>>>> then I have a patch for this:
>>>>>
>>>>> http://cr.openjdk.java.net/~stefank/8194926/webrev.01/
>>>>> https://bugs.openjdk.java.net/browse/JDK-8194926
>>>>> 8194926: NMT: Clean up usage of
>>>>> get_record_virtual_memory_uncommit/release
>>>>
>>>> Thanks for the cleanup. Looks good to me.
>>>
>>> Oops.
>>>
>>> You do need
>>>
>>> static inline void record_virtual_memory_uncommit(void* addr,
>>> size_t size) { }
>>> 235 static inline void record_virtual_memory_release(void* addr,
>>> size_t size) { }
>>>
>>> in #if !INCLUDE_NMT section.
>>>
>>> Thanks,
>>>
>>> -Zhengyu
>>>
>>>>
>>>> -Zhengyu
>>>>
>>>>>
>>>>> While running the NMT jtreg tests with ZGC, I found that one of the
>>>>> tests used ints to parse size_t values. Here's and upstream patch
>>>>> for that.
>>>>>
>>>>> http://cr.openjdk.java.net/~stefank/8194925/webrev.01/
>>>>> https://bugs.openjdk.java.net/browse/JDK-8194925
>>>>> 8194925: NMT: SummarySanityCheck test can't parse values > max_jint
>>>>>
>>>>> Thanks,
>>>>> StefanK
>>>>>
>>>>> On 2018-01-11 10:09, Stefan Karlsson wrote:
>>>>>> [Looping in Zhengyu]
>>>>>>
>>>>>> Inlined:
>>>>>>
>>>>>> On 2018-01-11 07:56, Per Liden wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 01/10/2018 05:01 PM, Stefan Karlsson wrote:
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> Please review this patch to fix a bug in the recent NMT
>>>>>>>> implementation for ZGC.
>>>>>>>>
>>>>>>>> http://cr.openjdk.java.net/~stefank/zgc/zNMTBugFix/webrev.01
>>>>>>>
>>>>>>> Change looks good, but the memTracker.cpp part should probably be
>>>>>>> split out into an upstream patch. Also, it feels like we should
>>>>>>> adjust the other user of this in os.cpp to use the new function.
>>>>>>
>>>>>>
>>>>>> Looking at the os.cpp function:
>>>>>>
>>>>>> bool os::uncommit_memory(char* addr, size_t bytes) {
>>>>>> bool res;
>>>>>> if (MemTracker::tracking_level() > NMT_minimal) {
>>>>>> Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
>>>>>> res = pd_uncommit_memory(addr, bytes);
>>>>>> if (res) {
>>>>>> tkr.record((address)addr, bytes);
>>>>>> }
>>>>>> } else {
>>>>>> res = pd_uncommit_memory(addr, bytes);
>>>>>> }
>>>>>> return res;
>>>>>> }
>>>>>>
>>>>>> Is there a reason why the Tracker object is created before the
>>>>>> pd_uncommit_memory, while the record() and ~Tracker is called after?
>>>>>>
>>>>>> Could we change the code above to:
>>>>>>
>>>>>> bool os::uncommit_memory(char* addr, size_t bytes) {
>>>>>> bool res = pd_uncommit_memory(addr, bytes);
>>>>>> if (res && MemTracker::tracking_level() > NMT_minimal) {
>>>>>> Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
>>>>>> tkr.record((address)addr, bytes);
>>>>>> }
>>>>>> return res;
>>>>>> }
>>>>>>
>>>>>> or even:
>>>>>>
>>>>>> bool os::uncommit_memory(char* addr, size_t bytes) {
>>>>>> bool res = pd_uncommit_memory(addr, bytes);
>>>>>> if (res) {
>>>>>> MemTracker::record_virtual_memory_uncommit(addr, bytes)
>>>>>> }
>>>>>> return res;
>>>>>> }
>>>>>>
>>>>>> Then these functions would look very similar to the commit functions:
>>>>>>
>>>>>> bool os::commit_memory(char* addr, size_t size, size_t
>>>>>> alignment_hint,
>>>>>> bool executable) {
>>>>>> bool res = os::pd_commit_memory(addr, size, alignment_hint,
>>>>>> executable);
>>>>>> if (res) {
>>>>>> MemTracker::record_virtual_memory_commit((address)addr, size,
>>>>>> CALLER_PC);
>>>>>> }
>>>>>> return res;
>>>>>> }
>>>>>>
>>>>>>
>>>>>> I see that Tracker() and ~Tracker() locks and unlocks
>>>>>> ThreadCritical. Do we need to be in "thread critical" while
>>>>>> unmapping memory?
>>>>>>
>>>>>> If we can do the change above, then I think we can get rid of
>>>>>> get_virtual_memory_uncommit_tracker and
>>>>>> get_virtual_memory_release_tracker.
>>>>>>
>>>>>> Thanks,
>>>>>> StefanK
>>>>>>
>>>>>>>
>>>>>>> cheers,
>>>>>>> Per
>>>>>>>
>>>>>>>>
>>>>>>>> The uncommit path was executed even when NMT was turned off.
>>>>>>>> Because of this we hit the following assertion when pages were
>>>>>>>> detached:
>>>>>>>>
>>>>>>>> # Internal Error (.../services/memTracker.hpp:231), pid=12751,
>>>>>>>> tid=2738
>>>>>>>> # assert(tracking_level() >= NMT_summary) failed: Check by caller
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> StefanK
More information about the zgc-dev
mailing list