Skip to content

Conversation

@mithileshz
Copy link
Contributor

Fixes #4735

@OsirisTerje OsirisTerje changed the title Change byte allocation to be on the stack instead of the heap for performance improvements WIP: Change byte allocation to be on the stack instead of the heap for performance improvements Jun 25, 2024
@mithileshz mithileshz marked this pull request as ready for review June 30, 2024 15:23
@mithileshz mithileshz changed the title WIP: Change byte allocation to be on the stack instead of the heap for performance improvements Change byte allocation to be on the stack instead of the heap for performance improvements Jun 30, 2024
@OsirisTerje
Copy link
Member

The StreamsComparer does not have direct unit tests. It could be an idea to add this since it is being directly modified here.

byte[] bufferActual = new byte[BUFFER_SIZE];
#else
Span<byte> bufferExpected = stackalloc byte[BUFFER_SIZE];
Span<byte> bufferActual = stackalloc byte[BUFFER_SIZE];
Copy link
Member

Choose a reason for hiding this comment

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

The BUFFER_SIZE is 4096. That is a bit more than what is recommended for stackalloc, which says up to 1KB. Should this be a concern here?

Copy link
Member

Choose a reason for hiding this comment

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

I agree, even 1KB is on the higher side as I've seen 256 bytes often as a limit to stackalloc.

One other option here could be ArrayPool.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll look into ArrayPool - haven't used it before so will investigate and come back later today.

@stevenaw
Copy link
Member

stevenaw commented Jul 3, 2024

Thanks for adding me here @OsirisTerje

@mithileshz Welcome back and thank you as well for noticing the room for improvement here 🙂
I'm away on vacation without a laptop but can participate better upon my return. For now I've left a suggestion above in response @OsirisTerje 's comment.

@mithileshz
Copy link
Contributor Author

mithileshz commented Jul 3, 2024

The StreamsComparer does not have direct unit tests. It could be an idea to add this since it is being directly modified here.

@OsirisTerje There are tests inside EqualConstraintTests inside the region StreamEquality. As this change doesn't change the behaviour of the StreamComparer, I didn't add any extra tests as those would have been covered by the tests in class?

@OsirisTerje
Copy link
Member

OsirisTerje commented Jul 12, 2024

4 tests failing.

1) Failed : NUnit.Framework.Tests.Constraints.EqualConstraintTests+StreamEquality.ShortReadingMemoryStream_AssertErrorMessageFailurePointIsCorrect
  Assert.That(ex?.Message, Does.Contain("Stream lengths are both 9. Streams differ at offset 8."))
  Expected: String containing "Stream lengths are both 9. Streams differ at offset 8."
  But was:  "  Assert.That(entryStream, Is.EqualTo(expectedStream))
  Stream lengths are both 9. Streams differ at offset 2552.
"
   at NUnit.Framework.Tests.Constraints.EqualConstraintTests.StreamEquality.ShortReadingMemoryStream_AssertErrorMessageFailurePointIsCorrect() in /_/src/NUnitFramework/tests/Constraints/EqualConstraintTests.cs:line 257

2) Failed : NUnit.Framework.Tests.Constraints.EqualConstraintTests+StreamEquality.UnSeekableActualAndExpectedStreamsEqual
  Assert.That(actualStream, Is.EqualTo(expectedStream))
  Streams differ at offset 2552.
   at NUnit.Framework.Tests.Constraints.EqualConstraintTests.StreamEquality.UnSeekableActualAndExpectedStreamsEqual() in /_/src/NUnitFramework/tests/Constraints/EqualConstraintTests.cs:line 197

3) Failed : NUnit.Framework.Tests.Constraints.EqualConstraintTests+StreamEquality.UnSeekableActualStreamEqual
  Assert.That(entryStream, Is.EqualTo(expectedStream))
  Streams differ at offset 2552.
   at NUnit.Framework.Tests.Constraints.EqualConstraintTests.StreamEquality.UnSeekableActualStreamEqual() in /_/src/NUnitFramework/tests/Constraints/EqualConstraintTests.cs:line 147

4) Failed : NUnit.Framework.Tests.Constraints.EqualConstraintTests+StreamEquality.UnSeekableExpectedStreamEqual
  Assert.That(actualStream, Is.EqualTo(expectedStream))
  Streams differ at offset 2552.
   at NUnit.Framework.Tests.Constraints.EqualConstraintTests.StreamEquality.UnSeekableExpectedStreamEqual() in /_/src/NUnitFramework/tests/Constraints/EqualConstraintTests.cs:line 171
```

Copy link
Member

@stevenaw stevenaw left a comment

Choose a reason for hiding this comment

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

Great work @mithileshz , results are looking promising so far!
I've proactively left a few helpful pointers since you mentioned you were a little new to using ArrayPool.

Copy link
Member

@OsirisTerje OsirisTerje left a comment

Choose a reason for hiding this comment

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

lgtm

@mithileshz mithileshz requested a review from stevenaw July 12, 2024 21:11
Copy link
Member

@stevenaw stevenaw left a comment

Choose a reason for hiding this comment

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

Fantastic, looks like your change speeds things up and lowers allocations.
LGTM, thanks for your contribution @mithileshz

@stevenaw stevenaw merged commit 18ce55b into nunit:main Jul 12, 2024
@stevenaw stevenaw changed the title Change byte allocation to be on the stack instead of the heap for performance improvements Change byte allocation to be pooled for performance improvements Jul 12, 2024
@mithileshz mithileshz deleted the stackalloc-change branch July 13, 2024 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

StreamComparer - Pool allocating the byte array reduces memory allocation by 96%

3 participants