New chunk should be equal/larger than the one it replaces#17219
Conversation
|
@dotnet-bot test Windows_NT x64 Checked corefx_baseline |
| @@ -486,12 +486,18 @@ public int Length | |||
| // Avoid possible infinite capacity growth. See https://github.com/dotnet/coreclr/pull/16926 | |||
There was a problem hiding this comment.
this comment is now wrong?
// We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
// to ensure the original capacity is preserved.
There was a problem hiding this comment.
I'll move this to the if block.
| else | ||
| { | ||
| Debug.Assert(newLen == chunk.m_ChunkChars.Length, "The new chunk should be larger or equal to the one it is replacing."); | ||
| m_ChunkChars = chunk.m_ChunkChars; |
There was a problem hiding this comment.
// Special case where the capacity we want to keep corresponds exactly to the size of the content.
// Just take ownership of the array.
Not sure the assert is worth having now.
There was a problem hiding this comment.
Can you check there's a test that goes down this path?
There was a problem hiding this comment.
I'll move this comment into the else block
| { | ||
| Debug.Assert(newLen == chunk.m_ChunkChars.Length, "The new chunk should be larger or equal to the one it is replacing."); | ||
| m_ChunkChars = chunk.m_ChunkChars; | ||
| } |
There was a problem hiding this comment.
Is it worth asserting at the end of the method that Length == value
There was a problem hiding this comment.
Added this assert to the end:
Debug.Assert(Length == value, "Something went wrong setting Length.");
|
Can you please add specific to StringBuilder that fails before your change and passes after? We should not rely on other test libraries for coverage necessary to protect our functionality. |
danmoseley
left a comment
There was a problem hiding this comment.
thanks for fixing so quickly!
|
Will be adding test to corefx PR dotnet/corefx#28038 |
| Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength); | ||
| if (newLen > chunk.m_ChunkChars.Length) | ||
| { | ||
| // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk, |
There was a problem hiding this comment.
it's not the original capacity though. it's 120% of it at most. Maybe
// to ensure the capacity we want
| @@ -0,0 +1,19 @@ | |||
| Stack trace: | |||
| Frame Function Args | |||
| 00180238000 0018005D19E (00180223639, 00180223C39, 001802342F0, 000FFFFB720) | |||
There was a problem hiding this comment.
Actually you could add .exe.stackdump to our .gitignore at the root.
There was a problem hiding this comment.
oh no! didn't mean to add this :)
|
@dotnet-bot test Windows_NT x64 Checked corefx_baseline |
About the Use Case:The code snippet below is taken from failing test: This will result in a StringBuilder with with length of 1 and two chunks. In this case, it should be OK to reduce the Capacity value to 16 as we set Length to 0 and keep chunk array length the same value, rather than expanding the chunk length to 17 as we were doing prior to the change in PR #16926 |
|
Failures seem are infrastructure:
Windows_NT x64 Checked Build and Test (Jit - CoreFx) - passes which was failing on this code before |
Fixes #17205
In PR #16926 we changed the behavior on a non-empty StringBuilder such that it will not always grow the last chunk array length on
sb.Length=valueoperation where value is smaller than current Length.The goal for this change was to keep Capacity within finite range as we loop multiple times to Clear and Append and Insert into the StringBuilder.
This PR removes the assertion that makes sure we always grow it's last chunk array.
cc: @jkotas @danmosemsft @benaadams