RFR(s): 8073476: G1 logging ignores changes to PrintGC* flags via MXBeans

Bengt Rutisson bengt.rutisson at oracle.com
Mon Apr 20 08:34:19 UTC 2015


Hi Dima,

On 2015-04-17 15:51, Dmitry Fazunenko wrote:
> Bengt,
>
> Please find comments inline.
>
> On 17.04.2015 9:43, Bengt Rutisson wrote:
>>
>> Hi Dima,
>>
>> On 2015-04-16 15:36, Dmitry Fazunenko wrote:
>>> Hi Bengt,
>>>
>>> thanks for looking.
>>>
>>> On 16.04.2015 15:42, Bengt Rutisson wrote:
>>>>
>>>> Hello Dima,
>>>>
>>>> On 2015-04-16 13:40, Dmitry Fazunenko wrote:
>>>>> Hello,
>>>>>
>>>>> Would you review a simple fix in G1.
>>>>>
>>>>> Short description:
>>>>> after introduction G1Log - dynamic changes of PrintGC and 
>>>>> PrintGCDetails flag has no effect anymore, because G1Log looks for 
>>>>> these flags during initialization only. The fix: sync the log 
>>>>> level with the flags values.
>>>>>
>>>>> A huge thanks to Jesper who helped me a lot with my first product fix.
>>>>>
>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8073476
>>>>> Webrev: http://cr.openjdk.java.net/~dfazunen/8073476/webrev.06/
>>>>
>>>> Sorry, but I don't really like the way this is solved. With this 
>>>> approach calling G1GCPhaseTimes::print() suddenly has the side 
>>>> effect that it resets the log level. That's quite unexpected for 
>>>> me. Especially if you consider the code path in 
>>>> G1CollectedHeap::log_gc_footer() where we do this:
>>>>
>>>> void G1CollectedHeap::log_gc_footer(double pause_time_sec) {
>>>>   if (!G1Log::fine()) {
>>>>     return;
>>>>   }
>>>>
>>>>   if (G1Log::finer()) {
>>>>     ...
>>>>     g1_policy()->phase_times()->print(pause_time_sec);
>>>>     ...
>>>>   }
>>>>
>>>> If we don't have G1Log::fine() (which is PrintGC) enabled we will 
>>>> never call the print() method and will thus not detect any changes 
>>>> made by the MXBean. If we have G1Log::finer() enabled we enter the 
>>>> logging code, print other things at the "finer" level (which is 
>>>> PrintGCDetails) and then do the call to the print() method where we 
>>>> can suddenly decide that PrintGCDetails no longer is enabled and 
>>>> not do the rest of the logging. So for the same GC we will print 
>>>> some stuff at PrintGCDetails level and some things at another 
>>>> level. Strange.
>>>
>>> May it's not clear, but the change will have effect only if PrintGC 
>>> or PrintGCDetails has been changed during execution.
>>> Otherwise, the level will not change.
>>
>> I understand that, but what I was saying with the example above is 
>> that you will not get the desired effect if you change PrintGC or 
>> PrintGCDetails at runtime. If they are disabled, and then turn them 
>> on at runtime you will not enter the update code because of this 
>> check at the start of the log_gc_footer() method:
>>
>>   if (!G1Log::fine()) {
>>     return;
>>   }
>>
>>
>> Similarly turning them off at runtime will start to have an effect in 
>> the middle of a GC. Which is probably not the effect you are looking for.
> fine() invokes level(), level() invokes update(), so G1::fine() will 
> return the up to date value:
>
>     inline static bool fine() {
> -    return _level >= LevelFine;
> +    return level() >= LevelFine;
>     }
>
>     static LogLevel level() {
> +    // PringGC and PrintGCDetails are dynamic flags
> +    // _level should be in sync with the latest values
> +    update_level();
>       return _level;
>     }
>
Oh, I missed that you had changed fine() to call level(). This means 
that all calls to G1Log interface has side effects. I don't like that at 
all.

>>
>> This is why making the level() getter having the side effect of 
>> changing the log level is a bad idea. You have no control over when 
>> that happens.
>
> It must be up to those who change flags at runtime.
> But the following code should work:
>
> MXBean.set(PrintGC, false);
> System.gc();
> MXBean.set(PrintGC, true);
>
>>
>>>
>>> To me, it's strange, that when I disable PrintGC in G1 I still 
>>> seeing gc log messages...
>>> Or, I can't turn logging on during execution with G1.
>>> This works well for other collectors.
>>>
>>> Would it make sense to make PrintGC and PrintGCDetails unmanageable 
>>> in case of g1?
>>
>> I think they can be manageble but their changed states need to be 
>> handled more explicitly.
>>
>>>
>>>
>>>>
>>>>
>>>> I would prefer to have a hook when the MXBean changes the value and 
>>>> only update the level at that point.
>>>
>>> Yes, it would be ideal solution. But I haven't found such a 
>>> mechanism supported. And it's unlikely worth adding just for this case.
>>> In my version, the sync will be done more frequently.
>>
>> The sync is done very frequently. Actually way too often in my view.
>>
>> I would prefer that you investigate the hook in the MXBean change so 
>> we know how much work that would be. 
>
> It was my first intention, but I haven't found a way how to implement it.

I think what you need to do is to extend the Flag class with an update() 
method and call the method in WriteableFlags::set_flag().

>
>> If that is not possible I think a better solution is to call 
>> G1Log::update_level() *once* at the start of a GC. That way the log 
>> level is always consistent throughout the GC.
>
> Yes, this is a good idea!

Yes, it is much cleaner.

>
>>
>>>
>>>>
>>>> Having said that I am not sure that this bug is worth fixing right 
>>>> now. I am currently working on the JEP to make the GC logging use 
>>>> the new unified logging format. That will change all of this and 
>>>> most likely remove the G1Log class all together. So, my suggestion 
>>>> would be to leave this as is for now and instead add the MXBean 
>>>> requirement to the unified logging work.
>>>
>>> Yes, I'm aware of unified logging and expect that G1Log class will 
>>> go away someday.
>>> But I would like to be able to disable logging in JDK9, to not see 
>>> GC events occurred at the certain period of time.
>>
>> Can you explain more why this is important to fix right now? Unified 
>> logging is targeted for JDK 9.
>
> What I heard about unified logging is that there is no guarantee that 
> it will happen in JDK9 time frame.
> I need the feature now to develop tests based on analysis of logs: I 
> want to start logging not from begging, but after some steps.
>
> Will you be okay if G1Log::update_level() is invoked once per GC?

I would be ok with it, but I'm pretty convinced unified logging will 
make it in to JDK9 so if you can wait for it that might be better.

Thanks,
Bengt

>
> Thanks,
> Dima
>
>>
>> Thanks,
>> Bengt
>>
>>>
>>> Thanks,
>>> Dima
>>>
>>>
>>>>
>>>> Thanks,
>>>> Bengt
>>>>>
>>>>> Testing:
>>>>> I ran manually the test from the bug report to make sure the 
>>>>> change fixes the problem.
>>>>> A regression test will be delivered separately as a fix of 
>>>>> JDK-8077056 <https://bugs.openjdk.java.net/browse/JDK-8077056>
>>>>>
>>>>> Thanks,
>>>>> Dima 
>>>>
>>>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-gc-dev/attachments/20150420/e20e82fd/attachment.htm>


More information about the hotspot-gc-dev mailing list