[Fork] <no name>

CSharp · Console

/Program.cs

using System;
using System.Linq;
using System.Numerics;
using System.Diagnostics;

public static class Program
{
	static int[] preallocated = Enumerable.Range(1, 200_000).ToArray();
    public static void Main()
    {
        int[] array = new int[150_000];
        Array.Clear(array); FillIncremental(array, 1); Validate(array, 1);
        Array.Clear(array); FillIncremental_Simple(array, 1); Validate(array, 1);
		// preallocated
		Validate(preallocated, 1);	
		Array.Clear(array); Array.Copy(preallocated, array, array.Length); Validate(array, 1);
		
        const int loops = 2000;
        Console.WriteLine($"Array.Length: {array.Length:#,0}, Loops: {loops:#,0}");
        Measure("Vector", () => { for (int i = 0; i < loops; i++) FillIncremental(array, i); });
        Measure("Simple", () => { for (int i = 0; i < loops; i++) FillIncremental_Simple(array, i); });
		// preallocated
        Measure("ArrayCopy", () => { for (int i = 0; i < loops; i++) Array.Copy(preallocated, array, array.Length); });
		
        static void Validate(int[] array, int start) { if (array.Select((n, i) => n - i - start).Any(n => n != 0)) throw new Exception("Validation failed!"); }

        static void Measure(string title, Action action)
        {
            Console.WriteLine();
            Console.WriteLine($"{title}");
            Stopwatch stopwatch = new Stopwatch();
            long mem0 = GC.GetTotalAllocatedBytes(true);
            stopwatch.Start();
            action();
            stopwatch.Stop();
            long mem1 = GC.GetTotalAllocatedBytes(true);
            Console.WriteLine($"- Duration: {stopwatch.Elapsed.TotalMilliseconds:#,0} msec");
            Console.WriteLine($"- Allocated: {mem1 - mem0:#,0} bytes");
        }
    }

    /// <summary>
    /// Fills an array of integers with incremented values, starting from the 'startValue'.
    /// </summary>
    public static void FillIncremental(int[] array, int startValue = 0)
    {
        ArgumentNullException.ThrowIfNull(array);
        if (array.Length > 0 && startValue > (Int32.MaxValue - array.Length) + 1)
            throw new ArgumentOutOfRangeException(nameof(startValue));

        static void FillSimple(int[] array, int index, int length, int valueOffset)
        {
            int endIndex =  index + length;
            for (int i = index, j = index + valueOffset; i < endIndex; i++, j++)
                array[i] = j;
        }

        if (!Vector.IsHardwareAccelerated || array.Length < Vector<int>.Count)
        {
            FillSimple(array, 0, array.Length, startValue);
            return;
        }
        FillSimple(array, 0, Vector<int>.Count, startValue);
        Vector<int> vector = new(array);
        Vector<int> step = new(Vector<int>.Count);
        int endIndex = array.Length - Vector<int>.Count + 1;
        int i;
        for (i = Vector<int>.Count; i < endIndex; i += Vector<int>.Count)
        {
            vector += step;
            vector.CopyTo(array, i);
        }
        FillSimple(array, i, array.Length - i, startValue);
    }

    public static void FillIncremental_Simple(int[] array, int startValue)
    {
        ArgumentNullException.ThrowIfNull(array);
        if (array.Length > 0 && startValue > (Int32.MaxValue - array.Length) + 1)
            throw new ArgumentOutOfRangeException(nameof(startValue));
        for (int i = 0, j = 0 + startValue; i < array.Length; i++, j++) array[i] = j;
    }
}
;