From 9072500a881e7b82566c6830e1273b8246a39adf Mon Sep 17 00:00:00 2001 From: Joshua Yue Date: Tue, 4 Aug 2026 13:04:34 -0700 Subject: [PATCH] Restore BitArray constructor performance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4236475d-0243-488d-93d8-cd78e94d532b --- .../src/System/Collections/BitArray.cs | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs index 66ffc9fee7bcd7..0048a4aad99ed4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs @@ -172,10 +172,11 @@ private static byte[] CreateArray(ReadOnlySpan bytes, out int bitLength) throw new ArgumentException(SR.Format(SR.Argument_ArrayTooLarge, BitsPerByte), nameof(bytes)); } - bitLength = bytes.Length * BitsPerByte; - byte[] array = AllocateByteArray(bitLength); + int length = bytes.Length * BitsPerByte; + byte[] array = AllocateByteArray(length); bytes.CopyTo(array); + bitLength = length; return array; } @@ -192,7 +193,8 @@ public BitArray(bool[] values) { ArgumentNullException.ThrowIfNull(values); - _array = CreateArray(values, out _bitLength); + _array = CreateArray(values); + _bitLength = values.Length; } /// @@ -205,15 +207,15 @@ public BitArray(bool[] values) /// public BitArray(ReadOnlySpan values) { - _array = CreateArray(values, out _bitLength); + _array = CreateArray(values); + _bitLength = values.Length; } - private static byte[] CreateArray(ReadOnlySpan values, out int bitLength) + private static byte[] CreateArray(ReadOnlySpan values) { - bitLength = values.Length; - byte[] array = AllocateByteArray(bitLength); + byte[] array = AllocateByteArray(values.Length); - uint i = 0; + int i = 0; if (!BitConverter.IsLittleEndian || values.Length < Vector256.Count) { @@ -234,8 +236,8 @@ private static byte[] CreateArray(ReadOnlySpan values, out int bitLength) Vector512 isFalse = Vector512.Equals(vector, Vector512.Zero); ulong result = isFalse.ExtractMostSignificantBits(); - Unsafe.WriteUnaligned(ref Unsafe.Add(ref arrayRef, sizeof(ulong) * (i / 64u)), ~result); - i += (uint)Vector512.Count; + Unsafe.WriteUnaligned(ref Unsafe.Add(ref arrayRef, sizeof(ulong) * (i / 64)), ~result); + i += Vector512.Count; valuesAsBytes = valuesAsBytes.Slice(Vector512.Count); } } @@ -247,8 +249,8 @@ private static byte[] CreateArray(ReadOnlySpan values, out int bitLength) Vector256 isFalse = Vector256.Equals(vector, Vector256.Zero); uint result = isFalse.ExtractMostSignificantBits(); - Unsafe.WriteUnaligned(ref Unsafe.Add(ref arrayRef, sizeof(uint) * (i / 32u)), ~result); - i += (uint)Vector256.Count; + Unsafe.WriteUnaligned(ref Unsafe.Add(ref arrayRef, sizeof(uint) * (i / 32)), ~result); + i += Vector256.Count; valuesAsBytes = valuesAsBytes.Slice(Vector256.Count); } } @@ -265,20 +267,20 @@ private static byte[] CreateArray(ReadOnlySpan values, out int bitLength) uint upperResult = upperIsFalse.ExtractMostSignificantBits(); Unsafe.WriteUnaligned( - ref Unsafe.Add(ref arrayRef, sizeof(uint) * (i / 32u)), + ref Unsafe.Add(ref arrayRef, sizeof(uint) * (i / 32)), ~((upperResult << 16) | lowerResult)); - i += (uint)Vector128.Count * 2u; + i += Vector128.Count * 2; valuesAsBytes = valuesAsBytes.Slice(Vector128.Count * 2); } } Remainder: - for (; i < (uint)values.Length; i++) + for (; i < values.Length; i++) { - if (values[(int)i]) + if (values[i]) { - (uint byteIndex, uint bitOffset) = Math.DivRem(i, BitsPerByte); - array[byteIndex] |= (byte)(1 << (int)bitOffset); + (int byteIndex, int bitOffset) = Math.DivRem(i, BitsPerByte); + array[byteIndex] |= (byte)(1 << bitOffset); } } @@ -333,8 +335,8 @@ private static byte[] CreateArray(ReadOnlySpan values, out int bitLength) throw new ArgumentException(SR.Format(SR.Argument_ArrayTooLarge, BitsPerInt32), nameof(values)); } - bitLength = values.Length * BitsPerInt32; - byte[] array = AllocateByteArray(bitLength); + int length = values.Length * BitsPerInt32; + byte[] array = AllocateByteArray(length); if (BitConverter.IsLittleEndian) { @@ -345,6 +347,7 @@ private static byte[] CreateArray(ReadOnlySpan values, out int bitLength) BinaryPrimitives.ReverseEndianness(values, MemoryMarshal.Cast((Span)array)); } + bitLength = length; return array; }