RFR: 8295376: Improve debug agent virtual thread performance when no debugger is attached [v3]
Chris Plummer
cjplummer at openjdk.org
Fri Oct 28 03:46:43 UTC 2022
> This PR disables VIRTUAL_THREAD_START/END events when no debugger is attached. Some customers like to launch (in production mode) the JVM with the debug agent enabled, but with no debugger attached. This usually has a very minimal performance impact as long as the debugger remains unattached. Launching the JVM in this manner allows a debugger to later be attached if there are issues.
>
> In the past the debug agent has always kept THREAD_START/END events enabled, even when no debugger is attached. It does so to keep track of all existing threads, and this generally has minimal performance impact. However, with virtual threads there can be a very large number of virtual threads constantly being created and destroyed. With SkyNet, this results in as much as a 250x performance regression when the debug agent is enabled. A large part of this is due to all the VIRTUAL_THREAD_START/END events the debug agent has to deal with. When these events are disabled, the performance slowdown is more like 10x. This remaining 10x comes from JVMTI and is not addressed in this CR.
>
> The fix for this performance issue is to disable VIRTUAL_THREAD_START/END events when the debugger is not attached. This also requires forgetting about all known virtual threads when the debugger detaches since there will be no VIRTUAL_THREAD_END event to notify the debug agent when the virtual thread has died.
>
> I decided it was appropriate to not introduce this behavior change if the debug agent is launched with `includevirtualthreads=y` (the default is 'n'). `includevirtualthreads=y` is meant to help legacy debuggers, and indicates that the debug agent should try to track (remember) all vthreads that are running, and return them when `VirtualMachine.GetAllThreads` is called. `includevirtualthreads=y` sets `gdata->includeVThreads` true, so initially I had these changes conditional on `gdata->includeVThreads`. However, most of our testing is done with `includevirtualthreads=y` (an unfortunate necessity because of how most of the test are written). This made it hard to test these changes. So I introduced `gdata->rememberVThreadsWhenDisconnected`, and made the changes conditional on it instead. It defaults to be the same as `gdata->includeVThreads`. However, I did some testing with it manually set it to always be false to get better testing coverage. This could be made a debug agent flag set
table on the command line, but I opted not to since it's not really of interest to the typical debug agent user. I suppose it could be an undocumented flag just to use in testing. I can make this change if others agree.
>
> A couple notes on code flow that might help with understanding the changes:
> - When the connection is initiated, `debugLoop_run()` is called, and it calls `eventHandler_onConnect()` to enable the START/END callbacks.
> - When the connection is dropped, `debugLoop_run()` calls `debugInit_reset()`, which calls `eventHandler_reset()` to disable the START/END callbacks. A bit later `debugInit_reset()` calls `threadControl_reset()` to free up the vthread ThreadNodes.
Chris Plummer has updated the pull request incrementally with one additional commit since the last revision:
Remove waiting_for_active_callbacks flag
-------------
Changes:
- all: https://git.openjdk.org/jdk/pull/10865/files
- new: https://git.openjdk.org/jdk/pull/10865/files/9e4779cc..a2061e64
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jdk&pr=10865&range=02
- incr: https://webrevs.openjdk.org/?repo=jdk&pr=10865&range=01-02
Stats: 4 lines in 1 file changed: 0 ins; 3 del; 1 mod
Patch: https://git.openjdk.org/jdk/pull/10865.diff
Fetch: git fetch https://git.openjdk.org/jdk pull/10865/head:pull/10865
PR: https://git.openjdk.org/jdk/pull/10865
More information about the serviceability-dev
mailing list