Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Suppress the execution context per operation #2974

Closed
wants to merge 4 commits into from

Conversation

davidfowl
Copy link
Member

@davidfowl davidfowl commented Oct 2, 2018

Today we capture and restore the execution context per Socket operation. There's no need to do that because it already happens in the async state machine.

I need to measure the performance since we're making an additional method call per operation to save it on the other side, it might be a wash. Ideally, we would just use https://github.com/dotnet/corefx/issues/32582

BEFORE

image

AFTER

image

Look at that beautiful flattened frame 😄. This is the code being avoided https://github.com/dotnet/coreclr/blob/302630ed5a3730470e9ffeeebcd38c737c03963d/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs#L126-L202

Copy link
Contributor

@muratg muratg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you run the full test suite?

@@ -17,9 +18,12 @@ public SocketAwaitableEventArgs WaitForDataAsync()
{
_awaitableEventArgs.SetBuffer(Array.Empty<byte>(), 0, 0);

if (!_socket.ReceiveAsync(_awaitableEventArgs))
using (ExecutionContext.SuppressFlow())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the follow already be suppressed when it gets here? (in which case this call would throw)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlikely but I can add the crazy code. Regardless, I’m sad this is per call instead of per construction

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flow can't be suppressed here, this API is called from a single place in the code base.

@davidfowl
Copy link
Member Author

davidfowl commented Oct 3, 2018

Did you run the full test suite?

Not sure what you mean? The regular tests? Yes they run as part of the PR and the execution context doesn't need to be captured here because it's already captured and restored by the calling code.

@davidfowl
Copy link
Member Author

@dotnet-bot test Windows Debug x64 Build

@davidfowl davidfowl requested review from halter73 and Tratcher October 3, 2018 06:31
@halter73
Copy link
Member

halter73 commented Oct 3, 2018

What's the primary motivation for this: perf or less stack frames in debug/exception output? Am I correct in understanding you expect the perf to stay the same?

@davidfowl
Copy link
Member Author

What's the primary motivation for this: perf or less stack frames in debug/exception output? Am I correct in understanding you expect the perf to stay the same?

Perf should be better or the same. It'll be absolutely better when we get dotnet/corefx#32582.

@davidfowl
Copy link
Member Author

Looks slightly faster on the PlatformPlaintext benchmark:

Before

RPS CPU (%) Memory (MB) Avg. Latency (ms) Startup (ms) First Request (ms) Latency (ms)
3,078,291 79 297 2.2 189 47.4 0.5

After

RPS CPU (%) Memory (MB) Avg. Latency (ms) Startup (ms) First Request (ms) Latency (ms)
3,184,934 71 302 2.2 191 47 0.5


protected AsyncFlowControl? SuppressExecutionContext()
{
return ExecutionContext.IsFlowSuppressed() ? (AsyncFlowControl?)null : ExecutionContext.SuppressFlow();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can using a null nullable? (Tested, yes you can)

That's nice and elegant :)

@davidfowl
Copy link
Member Author

davidfowl commented Oct 4, 2018

Running the performance numbers again to make sure they weren't all noise:

Before

RPS CPU (%) Memory (MB) Avg. Latency (ms) Startup (ms) First Request (ms) Latency (ms)
3,170,415 83 323 1.8 191 43.3 0.5

After

RPS CPU (%) Memory (MB) Avg. Latency (ms) Startup (ms) First Request (ms) Latency (ms)
3,194,044 80 309 1.8 189 47.2 0.7

Might be a wash.

@benaadams
Copy link
Contributor

Should skip out this bit
image

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants