RFR: 8145934: Make ttyLocker equivalent for Unified Logging framework
Marcus Larsson
marcus.larsson at oracle.com
Thu Mar 31 08:53:00 UTC 2016
Any further feedback on this?
On 03/18/2016 02:33 PM, Marcus Larsson wrote:
> Hi again,
>
> New webrev:
> http://cr.openjdk.java.net/~mlarsson/8145934/webrev.02/
>
> Incremental:
> http://cr.openjdk.java.net/~mlarsson/8145934/webrev.alt-02/
>
> Made all allocations regular C heap allocations because of the
> problems with resource allocations that Thomas brought up. We can do a
> follow up change for resource allocation support if we really need it.
> Also added some more tests for scoped messages.
>
>
> On 02/17/2016 12:19 AM, John Rose wrote:
>> On Feb 16, 2016, at 8:32 AM, Marcus Larsson
>> <marcus.larsson at oracle.com <mailto:marcus.larsson at oracle.com>> wrote:
>>>
>>> Alternative version where a LogMessage automatically writes its
>>> messages when it goes out of scope:
>>> http://cr.openjdk.java.net/~mlarsson/8145934/webrev.alt/
>>> <http://cr.openjdk.java.net/%7Emlarsson/8145934/webrev.alt/>
>>
>>
>> I like this, with the LogMessageBuffer that does the heavy work, and
>> the [Scoped]LogMessage which is the simplest way to use it.
>>
>> The LogMessageBuffer should have a neutral unallocated state, for use
>> through the LogMessage macro. I.e., is_c_allocated should be a
>> three-state flag, including 'not allocated at all'. That way, if you
>> create the thing only to ask 'is_debug' and get a false answer, you
>> won't have done more than a few cycles of work. Probably the
>> set_prefix operation should be lazy in the same way.
>
> Fixed. Since I removed the resource allocation completely I could keep
> it as a boolean.
>
>>
>> I think the destructor should call a user-callable flush function,
>> something like this:
>>
>> ~ScopedLogMessage() { flush(); }
>> // in LogMessageBuffer:
>> void flush() {
>> if (_line_count > 0) {
>> _log.write(*this);
>> reset();
>> }
>> }
>> void reset() {
>> _line_count = 0;
>> _message_buffer_size = 0;
>> }
>>
>> It will be rare for user code to want to either flush early or cancel
>> pending output, but when you need it, it should be there.
>
> Fixed.
>
>>
>>> I still prefer the first patch though, where messages are neither
>>> tied to a particular log, nor automatically written when they go out
>>> of scope. Like I've said, the explicit write line makes it easier to
>>> read the code.
>>
>> There's a tradeoff here: It's easier to read the *logging* code if
>> all the *logging* operations are explicit. But the point of logging
>> code is to add logging to code that is busy doing *other* operations
>> besides logging. That's why (I assume) people have been noting that
>> some uses of logging are "intrusive": The logging logic calls too
>> much attention to itself, and with attention being a limited
>> resource, it takes away attention from the actual algorithm that's
>> being logged about.
>>
>> The scoped (RAII) log buffer, with automatic write, is the best way I
>> know to reduce the intrusiveness of this auxiliary mechanism.
>
> Fair point. I'm going with the automatic write on out of scope.
>
>>
>> Of course, I'm interested in finding out what your everyday customers
>> think about it. (Rachel, Coleen, David, Dan?)
>>
>>> For comparison I've updated the first suggestion with the guarantee
>>> for unwritten messages, as well as cleaning it up a bit by moving
>>> the implementation to the .cpp rather than the .hpp.
>>> Full webrev:http://cr.openjdk.java.net/~mlarsson/8145934/webrev.01/
>>> <http://cr.openjdk.java.net/%7Emlarsson/8145934/webrev.01/>
>>> Incremental:http://cr.openjdk.java.net/~mlarsson/8145934/webrev.00-01/
>>> <http://cr.openjdk.java.net/%7Emlarsson/8145934/webrev.00-01/>
>>>
>>> Let me know what you think.
>>
>> That option is more intrusive than the RAII buffered log alias.
>>
>> Separately, the review thread on JDK-8149383 shows a use for
>> LogMessageBuffer to collect a complex log message. The log message
>> can then be sent down one of two log streams. Something like:
>>
>> if (need_to_log) {
>> ResourceMark rm;
>> LogMessageBuffer buf;
>> buf.write("Revoking bias of object " INTPTR_FORMAT " , mark "
>> INTPTR_FORMAT " , type %s , prototype
>> header " INTPTR_FORMAT
>> " , allow rebias %d , requesting thread "
>> INTPTR_FORMAT,
>> p2i((void *)obj),
>> (intptr_t) mark,
>> obj->klass()->external_name(),
>> (intptr_t) obj->klass()->prototype_header(),
>> (allow_rebias ? 1 : 0),
>> (intptr_t) requesting_thread);
>> if (!is_bulk)
>> log_info(biasedlocking).write(buf);
>> else
>> log_trace(biasedlocking).write(buf);
>> }
>>
>> It is important here (like you pointed out) that the LogMessageBuffer
>> is decoupled from log levels and streams, so that it can be used as a
>> flexible component of logic like this.
>>
>> But the commonest usage should (IMO) be supported by a scoped
>> auto-writing log alias.
>
> Yeah, I agree.
>
> Thanks,
> Marcus
More information about the hotspot-dev
mailing list