RFR: 8145934: Make ttyLocker equivalent for Unified Logging framework

Marcus Larsson marcus.larsson at oracle.com
Fri Mar 18 13:33:24 UTC 2016


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