Example #1
0
        [MethodImpl(MethodImplOptions.AggressiveInlining)] // forced to ensure no perf drop for small memory buffers (hot path)
        internal static unsafe T[] AllocateUninitializedArray <T>(int length)
        {
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                return(new T[length]);
            }

            // for debug builds we always want to call AllocateNewArray to detect AllocateNewArray bugs
#if !DEBUG
            // small arrays are allocated using `new[]` as that is generally faster.
            if (length < 2048 / Unsafe.SizeOf <T>())
            {
                return(new T[length]);
            }
#endif
            // kept outside of the small arrays hot path to have inlining without big size growth
            return(AllocateNewUninitializedArray(length));

            T[] AllocateNewUninitializedArray(int length)
            {
                if (length < 0)
                {
                    throw new OverflowException();
                }

                T[] array = null;
                RuntimeImports.RhAllocateUninitializedArray(EETypePtr.EETypePtrOf <T[]>().RawValue, (uint)length, Unsafe.AsPointer(ref array));
                if (array == null)
                {
                    throw new OutOfMemoryException();
                }

                return(array);
            }
        }
Example #2
0
        internal static unsafe T[] AllocateUninitializedArray <T>(int length)
        {
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                return(new T[length]);
            }

            if (length < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, 0, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
#if DEBUG
            // in DEBUG arrays of any length can be created uninitialized
#else
            // otherwise small arrays are allocated using `new[]` as that is generally faster.
            //
            // The threshold was derived from various simulations.
            // As it turned out the threshold depends on overal pattern of all allocations and is typically in 200-300 byte range.
            // The gradient around the number is shallow (there is no perf cliff) and the exact value of the threshold does not matter a lot.
            // So it is 256 bytes including array header.
            if (Unsafe.SizeOf <T>() * length < 256 - 3 * IntPtr.Size)
            {
                return(new T[length]);
            }
#endif

            var pEEType = EETypePtr.EETypePtrOf <T[]>();

            T[] array = null;
            RuntimeImports.RhAllocateUninitializedArray(pEEType.RawValue, (uint)length, Unsafe.AsPointer(ref array));

            if (array == null)
            {
                throw new OutOfMemoryException();
            }

            return(array);
        }