Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[NativeAOT] Add null checks into memcpy/memset helpers" #98681

Merged
merged 1 commit into from
Feb 20, 2024

Conversation

jkotas
Copy link
Member

@jkotas jkotas commented Feb 19, 2024

Reverts #98547

@ghost
Copy link

ghost commented Feb 19, 2024

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Issue Details

Reverts #98547

Author: jkotas
Assignees: jkotas
Labels:

area-NativeAOT-coreclr

Milestone: -

@jkotas
Copy link
Member Author

jkotas commented Feb 19, 2024

The fix is not correct as discovered in #98623 (comment) .

Also, there may be unforeseen perf issues due to #98623 (comment) . I am thinking that we should revert it and wait for the proper fix from @EgorBo (#98623).

@jkotas jkotas requested a review from EgorBo February 19, 2024 22:40
@jkotas
Copy link
Member Author

jkotas commented Feb 19, 2024

cc @filipnavara

@filipnavara
Copy link
Member

filipnavara commented Feb 19, 2024

I’m fine with reverting and waiting for a more comprehensive fix. However, the Roslyn issue is not invalidating the fix completely. The managed code paths still trigger the NRE now where it would not previously trigger it. It’s only broken in the PInvoke path of the Memmove for large sizes. The performance cliff for SpanHelpers.Fill is also not present in the NativeAOT code since the usages of Unsafe.InitBlock are still in place. They are only removed in @EgorBo’s PR.

Copy link
Member

@EgorBo EgorBo left a comment

Choose a reason for hiding this comment

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

Up to you, hopefully, I'll land my PR tomorrow/this week 🙂

@jkotas
Copy link
Member Author

jkotas commented Feb 20, 2024

The performance cliff for SpanHelpers.Fill is also not present in the NativeAOT code since the usages of Unsafe.InitBlock are still in place.

The problematic call chain is user code -> Span.Clear -> SpanHelpers.ClearWithoutReferences -> Unsafe.InitBlock -> MemoryHelpers.MemSet -> SpanHelpers.Fill. I have not realized that we use Unsafe.InitBlock in the implementation of Span.Clear when approving the PR. It would make me more worried about the perf impact.

The change regressed performance of common memory clearing operations like Span.Clear or Memory.Clear by up to 2x+. For example:

using System.Diagnostics;
for (;;)
{
   var a = new byte[512];
   var sw = new Stopwatch();
   sw.Start();
   Work(a);
   Console.WriteLine(sw.ElapsedMilliseconds);
}

static void Work(byte[] a)
{
   for (int i = 0; i < 100_000_000; i++) a.AsSpan().Clear();
}

Results with PublishAot on Winx64, Intel 9:
Before #98547: ~390ms per iteration
After #98547: ~880ms per iteration

Bulk memory clearing is part of many operations. I am worried that we will start getting reports of random perf regressions and we will have to spend time chasing them down to this change if we keep it in.

@jkotas jkotas merged commit 9dc6ea6 into main Feb 20, 2024
108 of 110 checks passed
@jkotas jkotas deleted the revert-98547-naot-mem-helpers branch February 20, 2024 07:36
@filipnavara
Copy link
Member

I see. I thought you were referring to performance regressions for small blocks of constant size (which, presumably, still get optimized by JIT and don’t end up in the helper). I didn’t realise that SpanHelpers.Fill is so significantly slower for big blocks.

@github-actions github-actions bot locked and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants