RFR(XL): 8181917: Refactor UL LogStreams to avoid using resource area
Marcus Larsson
marcus.larsson at oracle.com
Mon Jun 19 13:49:29 UTC 2017
On 2017-06-19 15:47, Thomas Stüfe wrote:
>
>
> On Mon, Jun 19, 2017 at 3:37 PM, Marcus Larsson
> <marcus.larsson at oracle.com <mailto:marcus.larsson at oracle.com>> wrote:
>
>
> On 2017-06-19 15:16, Thomas Stüfe wrote:
>> Hi Marcus,
>>
>> On Mon, Jun 19, 2017 at 2:30 PM, Marcus Larsson
>> <marcus.larsson at oracle.com <mailto:marcus.larsson at oracle.com>> wrote:
>>
>> Hi Thomas,
>>
>> Thanks for your effort on this, great work!
>>
>>
>> On 2017-06-18 09:30, Thomas Stüfe wrote:
>>>
>>> --
>>>
>>> http://cr.openjdk.java.net/~stuefe/webrevs/8181917-refactor-ul-logstream/callsite-changes.webrev.00/webrev/
>>> <http://cr.openjdk.java.net/%7Estuefe/webrevs/8181917-refactor-ul-logstream/callsite-changes.webrev.00/webrev/>
>>>
>>
>> (Although this is a pre-existing issue, it might be a good
>> opportunity to clean it up now.)
>> In file loaderConstraints.cpp, class LoaderConstraintTable,
>> for functions purge_loader_constraints(), add_entry(),
>> check_or_update(), extend_loader_constraint() and
>> merge_loader_constraints():
>> A LogStream is created, but only ever used for print_cr():s,
>> which sort of defeats its purpose. It would be much simpler
>> just to use the LogTarget directly. This is actually what's
>> done for the converted log_ldr_constraint_msg().
>>
>>
>> I found some of those too, but can a sequence of
>> LogStream::print() calls really be replaced by a sequence of
>> LogTarget::print()/LogImpl::print()?
>>
>> LogStream buffers all input till newline is encountered, whereas
>> LogTarget::print (LogImpl::vwrite()->LogTagSet::vwrite()...) will
>> print one log line for each invocation, no?
>
> Indeed they can. There's nothing special going on in LogStreams to
> make the lines grouped in any way. Each print_cr on a LogStream is
> equivalent to a LogImpl::write call.
>
>
> Yes, but what about print() (without cr?) Maybe I am just slow...
>
> A sequence of
>
> Logstream ls;
> ls.print("<");
> ls.print("br");
> ls.print(">");
> ls.cr <http://ls.cr>();
>
> is really equivalent to
>
> Log(,,) log;
> log.info <http://log.info>("<");
> log.info <http://log.info>("br");
> log.info <http://log.info>(">\n");
>
> ?
>
> I would have thought that only LogStream::cr() will cause the stream
> to be flushed, hence it will write "<br>", whereas all log.info
> <http://log.info>() (or LogTarget::print()) calls would be logged as
> separate lines?
No you're right. I was just talking about cases where there's *only*
print_cr() calls, not when there are print() calls mixed in.
>
>
>>
>>
>> A similar but worse issue is present in sharedPathsMiscInfo.cpp:
>> Here, a LogStream is used to print incomplete lines without
>> any CR at the end. These messages will never be logged. Also,
>> the use of a stream here is unnecessary as well.
>>
>>
>> Yes, you are right, and it is also not enclosed in is_enabled().
>> Also, seems this coding is never tested, otherwise the assert in
>> ~LogStreamBase() would have fired because of missing stream flush().
>
> True. The old code would never had a chance to hit the assert due
> to the resource allocation destructor problem, but now we should
> be able to hit it with proper testing.
>
>> In compactibleFreeListSpace.cpp:
>>
>> 2200 ResourceMark rm;
>>
>> It should be safe to remove this ResourceMark.
>>
>>
>> Right.
>>
>>> These are the - mostly mechanical - changes to the many
>>> callsites. Most of these changes follow the same pattern. A
>>> code sequence using "xxx_stream()" was split into
>>> declaration of LogTarget or Log (usually the former), an
>>> "is_enabled()" query and declaration of LogStream on the
>>> stack afterwards. This follows the principle that the
>>> logging itself should be cheap if unused: the declaration of
>>> LogTarget is a noop, because LogTarget has no members. Only
>>> if is_enabled() is true, more expensive things are done,
>>> e.g. initializing the outputStream object and allocating
>>> ResourceMarks.
>>>
>>> Note that I encountered some places where logging was done
>>> without enclosing "is_enabled()" query - for instance, see
>>> gc/g1/heapRegion.cpp, or cms/compactibleFreeListSpace.cpp.
>>> As far as I understand, in these cases we actually do print
>>> (assemble the line to be printed), only to discard all that
>>> work in the UL backend because logging is not enabled for
>>> that log target. So, we pay quite a bit for nothing. I
>>> marked these questionable code sections with an "//
>>> Unconditional write?" comment and we may want to fix those
>>> later in a follow up issue?
>>
>> That sounds good to me. I found more sites where the logging
>> is unconditional (compactibleFreeListSpace.cpp,
>> parOopClosures.inline.hpp, g1RemSet.cpp), but we should fix
>> them all as a separate issue. I filed
>> https://bugs.openjdk.java.net/browse/JDK-8182466
>> <https://bugs.openjdk.java.net/browse/JDK-8182466>.
>>
>>
>> Ok! I'll add whatever I find as comments.
>>
>>>
>>> --
>>>
>>> http://cr.openjdk.java.net/~stuefe/webrevs/8181917-refactor-ul-logstream/api-changes.webrev.00/webrev/
>>> <http://cr.openjdk.java.net/%7Estuefe/webrevs/8181917-refactor-ul-logstream/api-changes.webrev.00/webrev/>
>>>
>>> The API changes mostly are simplifications. Before, we had a
>>> whole hierarchy of LogStream... classes whose only
>>> difference was how the backing memory was allocated. Because
>>> we now always use C-Heap, all this can be folded together
>>> into a single simple LogStream class which uses Cheap as
>>> line memory. Please note that I left
>>> "LogStreamNoResourceMark" and "LogStreamCHeap" for now and
>>> typedef'ed them to the one single LogStream class; I will
>>> fix those later as part of this refactoring.
>>
>> Looks good to me, as long as we get rid of the typedefs too
>> eventually. :)
>>
>>
>> Sure!
>>
>>
>>>
>>> --
>>>
>>> http://cr.openjdk.java.net/~stuefe/webrevs/8181917-refactor-ul-logstream/logstream-optimization.webrev.00/webrev/
>>> <http://cr.openjdk.java.net/%7Estuefe/webrevs/8181917-refactor-ul-logstream/logstream-optimization.webrev.00/webrev/>
>>
>> 56 // Prevent operator new for LogStream.
>> 57 // static void* operator new (size_t);
>> 58 // static void* operator new[] (size_t);
>> 59
>>
>> Should these be uncommented?
>>
>>
>> Oh, right. I have to play a bit more, was unsure whether that
>> coding actually does what I want it to do, prevent
>> ResourceObj::operator new from running. Will test a bit more.
>
> Alright, sounds good.
>
> Marcus
>
>>
>> Thanks again,
>> Marcus
>>
>>
>> Thanks for your review! I'll prepare an updated patch.
>>
>> ..Thomas
>>
>
>
More information about the hotspot-dev
mailing list