Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Conversation

@jkotas
Copy link
Member

@jkotas jkotas commented Jun 7, 2018

  • Allocate NativeOverlapped on unmanaged heap
  • It made PinnableBufferCache unnecessary and allowed me to delete it
  • I have also deleted overlapped handle bashing that allowed pending overlapped operations to not block appdomain unloading. It is not used today and unlikely to be ever needed again.

Fixes #17909

{
private OverlappedData m_overlappedData;
private static PinnableBufferCache s_overlappedDataCache = new PinnableBufferCache("System.Threading.OverlappedData", () => new OverlappedData());
private OverlappedData _overlappedData;
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 split between Overlapped and OvelappedData is not necessary either anymore. I may be able to eliminate the split as well.

@jkotas
Copy link
Member Author

jkotas commented Jun 7, 2018

Perf results:

Synchronous alloc/free is 1.5x faster:

    for (int i = 0; i < 10000000; i++)
    {
        var o = new Overlapped();
        var p = o.UnsafePack(callback, data);
        Overlapped.Free(p);
    }

Asynchronous alloc/free is 1.1x faster:

    for (int i = 0; i < 10000000; i++)
    {
        var o = new Overlapped();
        var p = o.UnsafePack(callback, data);
        Task.Run(() => { Overlapped.Free(p); });
    }

Object **pRef = (Object **)pObjRef;
_ASSERTE(lp2);
promote_func* callback = (promote_func*)lp2;
callback(pRef, (ScanContext *)lp1, GC_CALL_PINNED);
Copy link
Member Author

Choose a reason for hiding this comment

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

@Maoni0 @davmason This is changing contract of the local GC. Do I need to worry about it?

Copy link
Member

Choose a reason for hiding this comment

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

I don't see how this affects LocalGC... it's just making a callback that's implemented internally by the GC.

sorry I haven't had time to look at the rest of the changes - do you mind explaining why you are not passing the GC_CALL_PINNED flag anymore? if the object is now a native obj, it wouldn't need to call the callback at all - GC is not going to do anything with the object. do we still have Overlapped managed objects at all anymore (or did you split up the native part so the managed part doesn't need to be pinned)? if not then do we still need this async pinned handle type?

Copy link
Member Author

Choose a reason for hiding this comment

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

We still have Overlapped managed objects with this change, but the ASYNC handles do not pin them anymore - only the data arrays that they are pointing to are pinned by the ASYNC handles with this change.

It is the change in the GC contract: the ASYNC handles were pinning the overlapped objects before this change and they are not pinning the overlapped objects after this change.

Copy link
Member

Choose a reason for hiding this comment

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

ok then if you run with this version of clrgc.dll with an older version of clr.dll it wouldn't work. but this doesn't have to be a breaking change - we could communicate the version of the clr.dll to clrgc.dll and have async pinned handles do different things based on the minor version. but of course this requires some changes in LocalGC. what do you think, @davmason? otherwise you'd need to change the major version (GC_INTERFACE_MAJOR_VERSION) which is probably ok at this point if we think not many people will be using the 2.1 LocalGC anyway.

I know you see a big improvement in a microbenchmark - in real world scenarios the perf problem that these overlapped structures introduce is always about fragmentation and a lot of the fragmentation comes from the data that gets pinned so I am not sure how much improvement you'd see there.

Copy link

Choose a reason for hiding this comment

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

We probably need to rev the major version for 2.2 anyways, so I think we can just accept that and make the 2.2 local gc incompatible with 2.1. There are some other changes too that likely need an api change for 2.2 (like the debugger notifications in #17769). If this were the only issue it might make sense to talk about ways to avoid it, but it seems inevitable at this point.

Copy link
Member Author

Choose a reason for hiding this comment

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

My primary motivation for this change has been code simplification. I have done the performance measurements just to ensure I am not regressing performance. The improvement was a nice surprise.

I have reved the GC interface version.

lpOverlapped->Internal = 0;

if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolIOEnqueue))
FireEtwThreadPoolIOEnqueue(lpOverlapped, OBJECTREFToObject(overlapped), false, GetClrInstanceId());
Copy link
Member Author

@jkotas jkotas Jun 7, 2018

Choose a reason for hiding this comment

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

@vancem @brianrob Are you aware of any tooling that uses the object in this event and that can get broken by this change? (The object is no longer pinned.)

Copy link
Member

Choose a reason for hiding this comment

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

I am not aware of any tooling that would be affected by moving the overlapped structure from the managed to native heap. Thanks for checking.

I suspect that in addition to improved throughput on alloc/free, this will also have a positive impact on the heap in cases where PinnableBufferCache wasn't able to do as well as we would have liked.

@stephentoub
Copy link
Member

-2000 lines of code. Perf improvement. Awesome.

@jkotas
Copy link
Member Author

jkotas commented Jun 8, 2018

@dotnet-bot test Windows_NT x64 Checked corefx_baseline
@dotnet-bot test Ubuntu x64 Checked corefx_baseline

@stephentoub
Copy link
Member

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test please ("java.nio.channels.ClosedChannelException")

@jkotas
Copy link
Member Author

jkotas commented Jun 9, 2018

@dotnet-bot test Windows_NT x64 Checked corefx_baseline
@dotnet-bot test Ubuntu x64 Checked corefx_baseline

@jkotas
Copy link
Member Author

jkotas commented Jun 9, 2018

@dotnet-bot test Windows_NT x64 Checked corefx_baseline
@dotnet-bot test Ubuntu x64 Checked corefx_baseline

@jkotas jkotas merged commit 911d332 into dotnet:master Jun 9, 2018
@jkotas jkotas deleted the overlapped branch June 9, 2018 20:44
jkotas added a commit to dotnet/corert that referenced this pull request Jun 18, 2018
dotnet-bot pushed a commit that referenced this pull request Jun 18, 2018
jkotas added a commit that referenced this pull request Jun 18, 2018
jkotas added a commit that referenced this pull request Jun 18, 2018
dotnet-bot pushed a commit to dotnet/corefx that referenced this pull request Jun 18, 2018
Port dotnet/coreclr#18360 to CoreRT

Signed-off-by: dotnet-bot <[email protected]>
Signed-off-by: dotnet-bot-corefx-mirror <[email protected]>
jkotas added a commit to dotnet/corefx that referenced this pull request Jun 18, 2018
Port dotnet/coreclr#18360 to CoreRT

Signed-off-by: dotnet-bot <[email protected]>
Signed-off-by: dotnet-bot-corefx-mirror <[email protected]>
// The split between Overlapped and OverlappedData should not be needed. It is required by the implementation of
// async GC handles currently. It expects OverlappedData to be a sealed type.
_overlappedData = new OverlappedData();
_overlappedData._overlapped = this;
Copy link
Member

Choose a reason for hiding this comment

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

@jkotas, I'm annotating this for nullability... any reason I can't make OverlappedData's ctor take the Overlapped as an argument? It would allow for the _overlapped field to then be readonly rather than nullable.

Copy link
Member Author

Choose a reason for hiding this comment

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

OverlappedData's ctor take the Overlapped as an argument

This should be fine. I do not see any issues with it.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks.

picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
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.

5 participants