RFR (S): 8077403: Remove guarantee from GenCollectedHeap::is_in()
Jon Masamitsu
jon.masamitsu at oracle.com
Mon Apr 13 16:53:33 UTC 2015
On 4/12/2015 6:29 AM, Bengt Rutisson wrote:
>
> Hi Jon,
>
> Thanks for looking at this.
>
> On 10/04/15 20:24, Jon Masamitsu wrote:
>> Bengt,
>>
>> I added a comment to the CR with some of the history (as I recall it),
>> about the desired restriction for the is_in() method.
>
> Thanks for adding this background.
>
> If it turns out that young_gen->is_in() needs to be used in a
> performance critical place then maybe we can optimize it? If we bypass
> the generation abstraction the young gen check could be turned in to
> two simple range checks instead of setting up space iterators and
> doing virtual calls as it is now. I don't think that work is useful to
> do right now. We have avoided the use of this method in performance
> critical code and Jesper is cleaning up the generation abstraction. We
> should wait until he is finished with the cleanups.
OK.
>> Would it
>> work to create an is_in_for_asserts() that would only be defined
>> under ASSERT to check that the uses were as expected? I know it
>> will not catch all the uses, but maybe those that are not covered
>> do not need the preciseness of is_in() and could use is_in_reserved()
>> instead.
> The reason the guarantee was there in the first place was that the
> is_in() method is not just called from asserts. I can add an
> is_in_for_asserts() method, but I still have to do something for the
> places (verification and dump code) that are in product code. So, I am
> not sure how adding a is_in_for_asserts() will help. Do you have a
> suggestion?
Having an is_in_for_asserts() would allow you to focus on the performance
critical uses. I would use is_in_reserved() for any performance
critical uses.
If is_in() is only defined under #ifdef ASSERT, are there less than a
dozen
place that need to be fixed?
>
> I was thinking about renaming is_in() to is_in_slow() to signal to
> users that it should nob be used in performance critical code. But
> that sounds like a check for something that is in a slow area. I'm
> open for naming suggestions.
The specification for is_in() makes it clear that it should not be used in
performance sensitive code so I'm also not sure what a good rename
would be or if a rename would help that much.
// Returns "TRUE" iff "p" points into the committed areas in the
generation.
// For some kinds of generations, this may be an expensive operation.
// To avoid performance problems stemming from its inadvertent use in
// product jvm's, we restrict its use to assertion checking or
// verification only.
>
> Also, note that the guarantee I remove was only present in
> GenCollectedHeap. G1 and Parallel does not do this check. So, I don't
> see how this guarantee helped us much since G1 and Parallel is where
> we mostly work on performance.
True, G1 and Parallel are the collectors that get performance
enhancements these days, but I have spent some time investigating
regression in CMS young pause times. Removing the guarantee
doesn't make such investigations easier.
Jon
>
> Thanks,
> Bengt
>
>>
>> Jon
>>
>> On 4/10/2015 5:34 AM, Bengt Rutisson wrote:
>>>
>>> Hi everyone,
>>>
>>> Can I have a couple of reviews for this small change?
>>>
>>> https://bugs.openjdk.java.net/browse/JDK-8077403
>>> http://cr.openjdk.java.net/~brutisso/8077403/webrev.00/
>>>
>>> The method CollectedHeap::is_in() has the following comment:
>>>
>>> // Returns "TRUE" iff "p" points into the committed areas of the
>>> heap.
>>> // Since this method can be expensive in general, we restrict its
>>> // use to assertion checking only.
>>>
>>> This is incorrect since we don't just use it for asserts. We also
>>> use it in os::print_location() which is in turn is used by several
>>> different code paths, such as verification, crash dumping and logging.
>>>
>>> In GenCollectedHeap::is_in() there is an attempt to verify that we
>>> only call this method from places that are not performance critical.
>>> So, its implementation looks like this:
>>>
>>> bool GenCollectedHeap::is_in(const void* p) const {
>>> #ifndef ASSERT
>>> guarantee(VerifyBeforeGC ||
>>> VerifyDuringGC ||
>>> VerifyBeforeExit ||
>>> VerifyDuringStartup ||
>>> PrintAssembly ||
>>> tty->count() != 0 || // already printing
>>> VerifyAfterGC ||
>>> VMError::fatal_error_in_progress(), "too expensive");
>>>
>>> #endif
>>> return _young_gen->is_in(p) || _old_gen->is_in(p);
>>> }
>>>
>>> It is quite odd that we do this check here and even more strange
>>> that it is only done in GenCollectedHeap and not in the other
>>> implementations (G1CollectedHeap and ParallelScavengeHeap).
>>>
>>> I doubt that this check is useful. The method is actually not that
>>> slow. It basically just iterates over the three spaces in young gen
>>> to do range checks and then does a single range check on the old
>>> gen. So, 4 range checks all together.
>>>
>>> Rather than having GenCollectedHeap::is_in() know about all callers
>>> of it I think we should remove the guarantee.
>>>
>>> The method CollectedHeap::is_in() is also called by three versions
>>> of is_in_place() but these three methods are unused, so I remove
>>> them as part of this patch.
>>>
>>> The method CollectedHeap::is_in_or_null() is only used in asserts,
>>> so I made it DEBUG_ONLY.
>>>
>>> I also make two style change to ParallelScavengeHeap. I made the
>>> implementation of ParallelScavengeHeap::is_in() look more like the
>>> implementation of GenCollectedHeap::is_in(). That made
>>> ParallelScavengeHeap::is_in_reserved() stick out, so I made that
>>> look cosistent with the new version of ParallelScavengeHeap::is_in().
>>>
>>> Thanks,
>>> Bengt
>>
>
More information about the hotspot-gc-dev
mailing list