8323807: Async UL: Add a stalling mode to async UL #22770
+128
−39
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi,
In January of this year I took a stab at implementing a stalling mode for UL, see link: #17757 . I also talked about this feature in the mailing lists and seemed to receive positive feedback. With that PR, I also implemented a circular buffer. This PR didn't go through because 1. The stalling mode was broken 2. The complexity was a bit too large imho.
This PR does a much smaller change by only focusing on implementing the actual stalling.
The addition in terms of command line changes are the same as before, you can now specify the mode of your async logging:
The change in protocol is quite simple. If a producer thread
P
cannot fit a message into the buffer, itmalloc
s a message and exposes it via a shared pointer. It blocks all other producer threads from writing into the buffer. At the same time, the consumer thread (AsyncLogWriter
) will perform all writing. When the consumer thread has emptied the write buffer, it writes the stalled message, notifiesP
and releases all locks.P
then let's all other producer threads continue.We do this by having two locks:
Outer
andInner
. In our example above,P
prevents any other producers from progressing by holding the outer lock, but allows the consumer thread to progress by releasing the inner lock.In pseudo-code we have something like this in the stalling case.
Note! It is very important that the consumer prints all output found in the buffer before printing the stalled message. This is because logging is output in Program Order. In other words:
print(m0); print(m1);
means thatm0
must appear beforem1
in the log file.Note! Yes, we do force all threads to stall before the original stalled message has been printed. This isn't optimal, but I still have hope that we can switch to a faster circular buffer in the future (actually, I've got that code too). If logs are written to a SSD with a ~700MiB/s sequential write speed, then this will be negligible if stalls are not very common.
Some benchmarks
I did some basic benchmarking with Spring Boot Hello World and performing some HTTP requests while doing a JFR recording.
I ran the following command for drop, similar for stall and sync:
And I stressed the server by performing 100 000 requests over 100 concurrent connections with 4 threads participating.
The result speed wise is:
The size of the
stallinglog
is501MiB
and the size of thedroppinglog
is292MiB
, so the amount written is quite different. Note: We're logging 501MiB over a period of <7 seconds, this is a huge amount of logging.JFR measurements show the following results in JMC.
Stalling
Dropping
Sync
I believe that this form of stalling is sufficiently performant to serve as a middle-of-the-road choice for those who do not want to lose any log messages yet have fairly small safepoints.
Best regards,
Johan
Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/22770/head:pull/22770
$ git checkout pull/22770
Update a local copy of the PR:
$ git checkout pull/22770
$ git pull https://git.openjdk.org/jdk.git pull/22770/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 22770
View PR using the GUI difftool:
$ git pr show -t 22770
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/22770.diff
Using Webrev
Link to Webrev Comment