Request for review - 8011268: NPG: Free unused VirtualSpaceNodes

Coleen Phillimore coleen.phillimore at oracle.com
Fri Apr 5 12:01:27 UTC 2013


On 4/5/2013 6:45 AM, Mikael Gerdin wrote:
>
>
> On 2013-04-05 00:41, Coleen Phillimore wrote:
>>
>> Hi Jon,
>>
>> Mikael's review is more thorough than what I've looked at so far.  I
>> wanted to add to it and my own comments at the end.   I didn't realize
>> you were working on this.  This is far less code than changing our
>> allocation scheme to malloc!
>>
>> On 04/04/2013 08:28 AM, Mikael Gerdin wrote:
>>> Jon,
>>>
>>> On 2013-04-04 06:00, Jon Masamitsu wrote:
>>>> After class unloading deallocate any VirtualSpaceNodes not being used.
>>>
>>> The webrev is a bit confusing since it says for metaspace.cpp:
>>> rev 4373 : 8011173: NPG: Replace the ChunkList implementation with
>>> class FreeList<Metachunk>
>>> Reviewed-by: mgerdin
>>>
>>> this implies to me that the 8011173 patch is included in this webrev
>>> when in fact this webrev is incremental on top of that patch.
>>> I don't know if that was intentional or not but it confused me a bit
>>> when trying to apply this patch.
>>>
>>> I'm totally fine with incremental webrevs though, just as long as they
>>> are advertised as such :)
>>>
>>>>
>>>> When the classes for a dead class loader are unloaded, all the
>>>> Metachunks
>>>> that had been used by that class loader are put on the Metachunk
>>>> free list for later reuse.   If all the Metachunks allocated out of a
>>>> VirtualSpaceNode are on the Metachunk free list, remove the Metachunks
>>>>   from the free list and deallocate the VirtualSpaceNode.
>>>>
>>>> The constructor for VirtualSpaceNode was moved to be below the
>>>> definition of
>>>> SpaceManager.
>>>
>>> I'm not sure why you moved the VirtualSpaceNode constructor to after
>>> the definition of SpaceManager, but I see that
>>> {inc,dec}_container_count need to reference the expand_lock().
>>>
>>
>> You moved the constructor for VirtualSpaceNode but the gc baseline
>> doesn't have changes I made to it recently, so moving it will not get
>> the most recent changes from hotspot-rt.
>
> FWIW those changes are actually in hotspot-gc so Jon will need to 
> merge with them before pushing.

He should merge before moving this because I think a trivial mercurial 
merge might miss these changes, or mercurial might barf on the whole 
thing.  I don't know.  Just a warning.  I don't mind that it's moved.

>
>>
>>
>>> Also, when I applied your patch and looked at the code in eclipse it
>>> helpfully notified me that you are forgetting to initialize
>>> _container_count in the VirtualSpaceNode constructor that you moved.
>>>
>>> Why don't you set the Metachunk::_container field in
>>> Metachunk::initialize():
>>>
>>>  776   // Point the chunk at the space
>>>  777   Metachunk* result = Metachunk::initialize(chunk_limit,
>>> chunk_word_size);
>>>  778   return result;
>>
>> In fact, I believe the Metachunk constructor is never called. Pointers
>> are transformed into these.  If that's the case the Metachunk
>> constructors should be removed.
>
> I don't see where I said anything about the Metachunk constructor.
>
> But the line where we call Metachunk::initialize is where we 
> initialize the memory that we allocated for the chunk is set up.
>
> I would prefer it if we could replace this with a call to the 
> placement new operator and use a constructor to set up the Metachunk 
> object but I'm not going to go into that argument.

Yes, I agree with you, placement new would be a lot nicer and then the 
constructor would be called.   Right now it isn't and it's a bit 
confusing having a way to initialize these that you think might be 
called.  (I know you didn't say this, I'm piling, I mean adding, on).

>
>>
>>>
>>>  It's called from VirtualSpaceNode so you should be able to pass
>>> "this" along to Metachunk::initialize. That will save us the walking
>>> of VirtualSpaceList to find the correct node to increment the count 
>>> for.
>>>
>>> If you set up Metachunk::_container in Metachunk::_initialize you
>>> could also skip the wrapper for ChunkManager::chunk_freelist_allocate
>>> inside VirtualSpaceList and just add:
>>>
>>> if (next != NULL) {
>>>   next->container()->inc_container_count();
>>> }
>>> at the end of VirtualSpaceList::get_new_chunk
>>>
>>> You are not decreasing the _container_count when returning humongous
>>> chunks in ~SpaceManager:
>>> 2123     Metachunk* next_humongous_chunks = humongous_chunks->next();
>>> // here you could do a
>>> humongous_chunks->container()->dec_container_count();
>>> 2124
>>> chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
>>>
>>> You are already incrementing _container_count for humongous chunks
>>> allocated from the hum chunk free list because those allocations go
>>> through the chunk_freelist_allocate wrapper function you added.
>>>
>>> It also feels strange that inc_container_count() is private but
>>> dec_container_count and container_count() are public. I realize that
>>> it works currently because VirtualSpaceList is a friend of
>>> VirtualSpaceNode but it seems like a strange level of encapsulation.
>>>
>>>
>>> The class space only contains one VirtualSpaceNode currently, should
>>> we add some code to make sure that we don't accidentally free that
>>> memory?
>>>
>>
>> The class space can contain >1 virtual space nodes if
>> !UseCompressedKlassPointers right now so you can purge unused spaces.
>> I'm making this go away.
>>
>> It looks like you find the containing virtual space node when you
>> deallocate the chunks which looks really expensive.   Why not have all
>> the chunks have a field with their container when they are created or
>> reused?  Am I reading this wrong?   These two "contains()" calls at
>> lines 2033, 2034 are going to be killer.
>
> This is exactly what I was saying above:
>
> >> Why don't you set the Metachunk::_container field in
> >> Metachunk::initialize():
> >>
> >>  776   // Point the chunk at the space
> >>  777   Metachunk* result = Metachunk::initialize(chunk_limit,
> >> chunk_word_size);
>
> We could easily pass on the VirtualSpaceNode to Metachunk::initialize.
>

Ok. I didn't read the counter code so didn't match your comment.
>
>>
>>
>> At 932, you should not purge the current virtual space, I think, because
>> you might just allocate it again.
>
> There might be loads and loads of free chunks in the other virtual 
> spaces and we may be recovering from a spike in metaspace allocation.
> If we are able to release metaspace memory I think we should.
> It feels pretty unlikely that we'll end up with a VirtualSpaceNode 
> with a count of 0 so we should take every chance we get to free one up 
> IMO.

Maybe, I guess.   What were the tracing results of this change? (ques 
for Jon).   Do we see these things going away on our favorite nashorn 
application?

thanks,
Coleen

>
> /Mikael
>
>>
>> Around 928, why do you have to walk the virtual space itself? Why not
>> walk the linked list of free chunks for the container entry that matches
>> the virtual space node if the virtual space count is null? You could do
>> one walk and remove all entries with all virtual space nodes that are
>> matching if you are worried about the loop in the loop.   It has to find
>> the chunk in the free list anyway to remove it.
>>
>> This is a nit of mine.   Can you move the declaration at 805 to 807
>> where the initial value is returned?
>>
>> Thanks!
>> Coleen
>>
>>> /Mikael
>>>
>>>>
>>>> http://cr.openjdk.java.net/~jmasa/8011268/webrev.00/
>>>>
>>>> Thanks.
>>>>
>>>> Jon
>>




More information about the hotspot-gc-dev mailing list