[TEST] Time only the quit in ElegantQuitQuick, and bound it where the two outcomes are - #4488
Draft
thc1006 wants to merge 1 commit into
Draft
[TEST] Time only the quit in ElegantQuitQuick, and bound it where the two outcomes are#4488thc1006 wants to merge 1 commit into
thc1006 wants to merge 1 commit into
Conversation
… two outcomes are The case exists to catch a destruction that lets the polling background thread sleep out scheduled_delay_milliseconds_ instead of waking it. Measured on an idle host, that quit costs 0.1 to 0.5 ms; measured with the wakeup removed, it costs 256.5 to 256.9 ms, and there is nothing in between. The bound sat at 20 ms, which is close enough to the fast outcome that a host adding scheduling delay to a sub millisecond operation trips it. The 21 ms failure reported on open-telemetry#4265 is that, and the 247 ms one is a quit that really did wait the poll out. 100 ms partitions the same two sets: over 24 runs of each arm, no measurement landed between 20 and 100 ms, so the wider bound gives up no detection. The window now covers the quit alone. The request is finished first through the file's own waitForRequests(), which also removes the fixed 10 ms sleep that was standing in for it. Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4488 +/- ##
==========================================
- Coverage 83.13% 83.12% -0.00%
==========================================
Files 519 519
Lines 20256 20256
==========================================
- Hits 16837 16835 -2
- Misses 3419 3421 +2 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Fixes #4265.
The two failures reported on that issue are not the same failure, and only one of them is the test's fault.
What the case is measuring
ElegantQuitQuickdestroys the client while its background thread is polling, and checks that the destructor woke the thread rather than letting it sleep outscheduled_delay_milliseconds_, which is 256 ms. A missed wakeup makes the quit slow rather than wrong, so a duration is the only thing there is to assert.I measured both outcomes on this branch before changing anything. 24 runs of each, same binary, idle host:
curl_multi_wakeupremovedThe working quit costs 0.1 to 0.5 ms. A quit that waited the poll out costs 256.5 to 256.9 ms. Nothing lands between them.
Why 20 ms is the wrong bound and 100 ms is not just a larger one
The bound sat 20 ms above an operation that takes half a millisecond. A host that adds scheduling delay to that operation trips it while the wakeup is working perfectly. That is the
cost ms: 21in the issue.cost ms: 247is the other one. It matches the measured missed wakeup exactly, so the case was right that time, and disabling it would drop a signal it has already produced once.100 ms was chosen from the gap rather than by doubling. Both bounds partition those 48 measurements identically, so the wider one gives up no detection while removing the class of false alarm that 20 ms invites. I would rather not raise it further: 256 ms is what it has to stay under.
What else changed
The timed window used to open before
FinishAllSessions()with the request still going, after a fixedsleep_for(10ms)that was standing in for the request completing. The window now covers the quit alone, and the request is finished first throughwaitForRequests(), which this file already uses for the same purpose inSendGetRequest. That removes the sleep as well.The two response assertions moved above the window, where they now guard it rather than trail it.
Checks
curl_http_testpasses 26 of 26. The case passes 30 of 30 idle and 30 of 30 with 64 busy loops on a 32 core host, which is the load that makes the old bound interesting.Removing
curl_multi_wakeupstill turns the case red, atcost ms: 256. It is worth saying that this catches it 19 times in 24 rather than every time: with the wakeup gone, the poll is sometimes broken by the cancelled transfer instead. That was true of the old bound too, and it is why the failure on CI is intermittent rather than constant.One thing this does not fix
It does not explain why the wakeup was missed on the run that produced 247 ms.
wakeupBackgroundThread()is called more than once on the destruction path, and libcurl documents that "multiple calls to this function wake up the same waiting operation", so two wakeups collapsing into one while two poll iterations remain would produce exactly this. That is a hypothesis, not a measurement, and it belongs to the transport work in #4448 rather than to a test fix.For significant contributions please make sure you have completed the following items:
CHANGELOG.mdupdated for non-trivial changes - N/A, test only, no behaviour change