RFR: 8141211: Convert TraceExceptions to Unified Logging

John Rose john.r.rose at oracle.com
Fri Dec 18 04:13:24 UTC 2015


On Dec 17, 2015, at 11:39 AM, Thomas Stüfe <thomas.stuefe at gmail.com> wrote:
> 
> When we print it, we precede the multiline message with the decorators in the first line and indent the rest of the lines to the same position:
> 
> [time][pid][tid]  hallo1
>                   hallo2
>                   hallo3
> 
> This approach has served us quite well. We decided against locking done by the caller because users to minimize the danger of deadlocks.

I agree that buffering is a better approach than locking.
In the old logging system, large amounts of logging are
produced by the compiler threads, and is buffered separately
per thread.  Smaller amounts are dumped into a common "tty"
stream, which is available only to one thread at a time.

The effect of the ttyLocker is to ensure unbroken multi-line output.
It doesn't intrinsically need to block other writers.

Buffering is a great way to keep integrity without blocking.
This could be introduced into the new UL framework like this:

   LogHandle(logging) log0;
   if (log0.is_debug()) {
     LogBuffer log(log0);
     int result = compute_debug_result();
     log.debug("result = %d", result).trace(" tracing info");
     obj->print_on(log.debug_stream());
   }

Or just:
   { LogBuffer(logging) log;
     if (log.is_debug()) {
       int result = compute_debug_result();
       log.debug("result = %d", result).trace(" tracing info");
       obj->print_on(log.debug_stream());
   } }

The "log" is a separate object from "log0" which has the same API,
and buffers all output before flushing to the underlying "log0".
(The RAII destructor flushes.  Maybe it also has explicit flush.)

Note that "log" has true object state, whereas "log0" is just a
bundle of static methods.

Perhaps LogBuffer could be economically used inside the Log methods
themselves; currently they do buffering equivalent to what LogBuffer
does, but using random logic (see uses of constant LogBufferSize).
Basically, wherever a "printf" format is used with Log API points,
there is already a hidden buffer (it resizes at most once, since
there is just one printf call).

Optional parameters to LogBuffer would control behavior related
to (possibly) splitting very large outputs (like PrintAssembly),
or buffering to files (using the rotating archive mechanism).

This would provide a road to replacing the existing LogCompilation
implementation, which has thread-local logs buffered to temp files.

I.e., a long-lived, thread-local, file-backed LogBuffer would allow
a compiler thread to produce gigabytes of output, all properly
sequenced, with no interruptions and no blocking of other logs.

Having a separate layer "LogBuffer" for keeping lines together
will not penalize users of the underlying line-at-time facility.

— John


More information about the hotspot-runtime-dev mailing list