RFR: 8145934: Make ttyLocker equivalent for Unified Logging framework

Thomas Stüfe thomas.stuefe at gmail.com
Thu Mar 31 10:48:55 UTC 2016

Hi Marcus,

nice to see progress on that issue!

Unfortunately your patch did not apply to my freshly synced hs-rt
repository. So I took a "dry look" at your code, and here some feedback (by
no means complete, and also I am not a (R)eviewer):

- thank you for taking my input and avoiding resource area for memory. I am
still apprehensive about UL using NEW_C_HEAP_ARRAY instead of raw malloc()
here, but I see it has pros and cons.

- I am not sure about flockfile(): I really do not like file locks, this
always bites in customer scenarios. Also, by using this lock, are we not
just reintroducing the ttyLocker at a deeper level? Instead, how about
assembling the total message in memory - like it would appear in the file -
and print it in one go using ::write()? That usually is atomic. This way
you would have to write out the decorators for each line in memory as they
are added, but you could get rid of the _lines[] array and all its
surrounding code. So, no lock, less complicated code, at the cost of a bit
more memory usage.

- If I understand this correctly, there is no way to print part of a line
to the message object? So, if I would want to assemble a line from various
inputs, I would still have to assemble it on the stack and feed it to say
ScopedLogMessage::debug() in one go? Would it be posssible to get an
outputStream* from the ScopedLogMessage to write into?

- I like how you implemented os::log_vsnprintf(), using _vscprintf() on
windows. Would it be worthwhile to merge this with jio_vsnprintf(), which
does the same but returns -1 on truncation?

Kind Regards, Thomas

On Thu, Mar 31, 2016 at 10:53 AM, Marcus Larsson <marcus.larsson at oracle.com>

> 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
>>>                             " , allow rebias %d , requesting thread "
>>>                             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