RFR (S): G1: Use ArrayAllocator for BitMaps

Bengt Rutisson bengt.rutisson at oracle.com
Tue Jun 18 07:31:55 PDT 2013


Hi Coleen,

Thanks for looking at this!

On 6/18/13 3:21 PM, Coleen Phillimore wrote:
>
> Bengt,
> I had a look at this change also.   I would pick ResourceObj over 
> ValueObj for the ArrayAllocator class.  ValueObj really is embedded 
> and is used very consistently, and ResourceObj is usually used for 
> mixed cases like this.   Is there some complication to using ResourceObj?

Now I'm confused.

I'm fine with switching to ResourceObj, but I thought that was supposed 
to be a way of tagging objects that should be allocated in resource 
areas. Here is the comment in allocation.hpp that I am using as a reference:

// For objects allocated in the resource area (see resourceArea.hpp).
// - ResourceObj
//
// For objects allocated in the C-heap (managed by: free & malloc).
// - CHeapObj
//
// For objects allocated on the stack.
// - StackObj
//
// For embedded objects.
// - ValueObj


Currently ArrayAllocator is always embedded in another object, so I 
figured that David's point was valid that it should be a ValueObj. But 
for the ResourceObj class there is this comment:

//----------------------------------------------------------------------
// Base class for objects allocated in the resource area per default.
// Optionally, objects may be allocated on the C heap with
// new(ResourceObj::C_HEAP) Foo(...) or in an Arena with new (&arena)
// ResourceObj's can be allocated within other objects, but don't use
// new or delete (allocation_type is unknown).  If new is used to allocate,
// use delete to deallocate.

Which, I guess says that a ResourceObj can be used for pretty much 
anything. If that is right, what is the point of having the ResourceObj 
class?

Thanks,
Bengt

>
> Thanks,
> Coleen
>
>
> On 06/18/2013 12:57 AM, David Holmes wrote:
>> Reviewed.
>>
>> Thanks.
>>
>> David
>>
>> On 18/06/2013 2:50 PM, Bengt Rutisson wrote:
>>> On 6/18/13 5:34 AM, David Holmes wrote:
>>>> Seems reasonable to me.
>>>
>>> Thanks, David!
>>>
>>> BTW, I am not sure if you reviewed the whole change or just 
>>> commented on
>>> the StackObj vs. ValueObj issue. Can I list you as a reviewer of the
>>> change?
>>>
>>> Thanks,
>>> Bengt
>>>
>>>>
>>>> Thanks,
>>>> David
>>>>
>>>> On 17/06/2013 4:17 PM, Bengt Rutisson wrote:
>>>>>
>>>>> Hi David,
>>>>>
>>>>> On 6/17/13 5:23 AM, David Holmes wrote:
>>>>>> Hi Bengt,
>>>>>>
>>>>>> I don't think it makes sense to embed a StackObj into a ValueObj! 
>>>>>> But
>>>>>> then why is ArrayAllocator a StackObj? The only existing use of it I
>>>>>> can see also embeds it! So seems to me it should be a ValueObj in 
>>>>>> the
>>>>>> first place.
>>>>>
>>>>> Good point. I changed ArrayAllocator to be a ValueObj instead. New
>>>>> webrev here:
>>>>> http://cr.openjdk.java.net/~brutisso/8016556/webrev.01/
>>>>>
>>>>> Here is the diff compared to the last version:
>>>>>
>>>>> diff --git a/src/share/vm/memory/allocation.hpp
>>>>> b/src/share/vm/memory/allocation.hpp
>>>>> --- a/src/share/vm/memory/allocation.hpp
>>>>> +++ b/src/share/vm/memory/allocation.hpp
>>>>> @@ -665,7 +665,7 @@
>>>>>   // is set so that we always use malloc except for Solaris where 
>>>>> we set
>>>>> the
>>>>>   // limit to get mapped memory.
>>>>>   template <class E, MEMFLAGS F>
>>>>> -class ArrayAllocator : public StackObj {
>>>>> +class ArrayAllocator VALUE_OBJ_CLASS_SPEC {
>>>>>     char* _addr;
>>>>>     bool _use_malloc;
>>>>>     size_t _size;
>>>>>
>>>>>
>>>>> Thanks for looking at this!
>>>>> Bengt
>>>>>
>>>>>
>>>>>>
>>>>>> David
>>>>>>
>>>>>> On 14/06/2013 12:53 AM, Bengt Rutisson wrote:
>>>>>>>
>>>>>>> Hi everyone,
>>>>>>>
>>>>>>> Could I have a couple of review for this small change?
>>>>>>> http://cr.openjdk.java.net/~brutisso/8016556/webrev.00/
>>>>>>>
>>>>>>> Sending this request to the broad hotspot dev mailing list since it
>>>>>>> touches code in vm/utilities.
>>>>>>>
>>>>>>> Background:
>>>>>>>
>>>>>>> In the constructor for the ConcurrentMark class in G1 we set up one
>>>>>>> bit
>>>>>>> map per worker thread:
>>>>>>>
>>>>>>>    for (uint i = 0; i < _max_worker_id; ++i) {
>>>>>>> ...
>>>>>>>      _count_card_bitmaps[i] = BitMap(card_bm_size, false);
>>>>>>>      ...
>>>>>>>    }
>>>>>>>
>>>>>>> Each of these bitmaps are malloced, which means that the amount of
>>>>>>> C-heap we require grows with the number of GC worker threads we
>>>>>>> have. On
>>>>>>> a machine with many CPUs we get many worker threads by default. For
>>>>>>> example, on scaaa007 I get 79 GC worker threads. The size of the
>>>>>>> bitmaps
>>>>>>> also scale with the heap size. Since this large machine has a 
>>>>>>> lot of
>>>>>>> memory we get a large default heap as well.
>>>>>>>
>>>>>>> Here is the output from just running java -version with G1 on
>>>>>>> scaaa007:
>>>>>>>
>>>>>>> $ java -d64 -XX:+UseG1GC -XX:+PrintMallocStatistics -version
>>>>>>> java version "1.8.0-ea-fastdebug"
>>>>>>> Java(TM) SE Runtime Environment (build 1.8.0-ea-fastdebug-b92)
>>>>>>> Java HotSpot(TM) 64-Bit Server VM (build 25.0-b34-fastdebug, mixed
>>>>>>> mode)
>>>>>>> allocation stats: 35199 mallocs (221MB), 13989 frees (0MB), 35MB 
>>>>>>> resrc
>>>>>>>
>>>>>>> We malloc 221MB just by starting the VM. Most of the large 
>>>>>>> allocations
>>>>>>> are due to the BitMap allocations. My patch changes the BitMap
>>>>>>> allocations to use the ArrayAllocator instead. That class uses 
>>>>>>> mmap on
>>>>>>> Solaris if the size is larger than 64K.
>>>>>>>
>>>>>>> With this patch the output looks like this:
>>>>>>>
>>>>>>> $ java -d64 -XX:+UseG1GC -XX:+PrintMallocStatistics -version
>>>>>>> java version "1.8.0-ea-fastdebug"
>>>>>>> Java(TM) SE Runtime Environment (build 1.8.0-ea-fastdebug-b93)
>>>>>>> Java HotSpot(TM) 64-Bit Server VM (build
>>>>>>> 25.0-b34-internal-201306130943.brutisso.hs-gc-g1-mmap-fastdebug, 
>>>>>>> mixed
>>>>>>> mode)
>>>>>>> allocation stats: 35217 mallocs (31MB), 14031 frees (0MB), 35MB 
>>>>>>> resrc
>>>>>>>
>>>>>>> We are down to 31MB.
>>>>>>>
>>>>>>> Note that the ArrayAllocator only has this effect on Solaris 
>>>>>>> machines.
>>>>>>> Also note that I have not reduced the total amount of memory, just
>>>>>>> moved
>>>>>>> it from the C-heap to mapped memory.
>>>>>>>
>>>>>>> One complication with the fix is that the BitMap data structures 
>>>>>>> get
>>>>>>> copied around quite a bit. The copies are shallow copies, so we 
>>>>>>> don't
>>>>>>> risk re-doing the allocation. But since I am now embedding an
>>>>>>> ArrayAllocator in the BitMap structure the destructor for copies of
>>>>>>> the
>>>>>>> ArrayAllocator gets called every now and then. The BitMap 
>>>>>>> explicitly
>>>>>>> frees up the allocated memory when it thinks it is necessary. So,
>>>>>>> rather
>>>>>>> than trying to refactor the code to avoid copying I made it
>>>>>>> optional to
>>>>>>> free the allocated memory in the ArrayAllocator desctructor.
>>>>>>>
>>>>>>> I do think it would be good to review the BitMap code. It seems 
>>>>>>> a bit
>>>>>>> fishy that we pass around shallow copies. But I think my current
>>>>>>> change
>>>>>>> keeps the same behavior as before.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Bengt
>>>>>
>>>
>



More information about the hotspot-dev mailing list