How to quickly zero out an array?

87,077

Solution 1

Try Array.Clear():

Sets a range of elements in the Array to zero, to false, or to null (Nothing in Visual Basic), depending on the element type.

Solution 2

  • C++: memset(array, 0, array_length_in_bytes);

  • C++11: array.fill(0);

  • C#: Array.Clear(array, startingIndex, length);

  • Java: Arrays.fill(array, value);

Solution 3

UPDATE

Based on the benchmark regarding Array.Clear() and array[x] = default(T) performance, we can state that there are two major cases to be considered when zeroing an array:

A) There is an array that is 1..76 items long;

B) There is an array that is 77 or more items long.

So the orange line on the plot represents Array.Clear() approach.

The blue line on the plot represents array[x] = default(T) approach (iteration over the array and setting its values to default(T)).

enter image description here

You can write once a Helper to do this job, like this:

public static class ArrayHelper
{
    // Performance-oriented algorithm selection
    public static void SelfSetToDefaults<T>(this T[] sourceArray)
    {
        if (sourceArray.Length <= 76)
        {
            for (int i = 0; i < sourceArray.Length; i++)
            {
                sourceArray[i] = default(T);
            }
        }
        else { // 77+
             Array.Clear(
                 array: sourceArray,
                 index: 0,
                 length: sourceArray.Length);
        }
    }
}

Usage:

someArray.SelfSetToDefaults();

Remarks:

This test was undertaken having in mind .NET Framework 4.x

Solution 4

Array.Clear(integerArray, 0, integerArray.Length);

Solution 5

Several people have posted answers, then deleted them, saying that in any language a for loop will be equally performant as a memset or FillMemory or whatever.

For example, a compiler might chunk it into 64-bit aligned pieces to take advantage of a 64bit zero assignment instruction, if available. It will take alignment and stuff into consideration. Memset's implementation is certainly not trivial.

one memset.asm. Also see memset-is-faster-than-simple-loop.html.

Never underestimate the infinite deviousness of compiler and standard library writers.

Share:
87,077
esac
Author by

esac

I am a software developer primarily focused on WinForms development in C#. I have been in development for 10 years.

Updated on March 08, 2020

Comments

  • esac
    esac about 4 years

    I am currently doing it in a for loop, and I know in C there is the ZeroMemory API, however that doesn't seem to be available in C#. Nor does the somewhat equivalent Array.fill from Java exist either. I am just wondering if there is an easier/faster way?

  • esac
    esac over 14 years
    I did a test with my for loop vs Array.Clear(). Array.Clear() 2 million times in a loop for a 4K array took 620 ms. The for loop took 13030 ms.
  • Richard
    Richard over 10 years
    @esac And while that definitely answers your question, it's still an open question as to whether that remains true for all operating systems and hardware. I agree that Array.Clear() is going to be at least as fast as a for loop and probably faster, which makes Array.Clear() the obvious choice. (Plus, it's easier to read.)
  • Hi-Angel
    Hi-Angel almost 9 years
    I'd against the c-function memset in C++ in favor of the C++ std::fill. The memset usually in optimized code becomes a call to the library memset, whilst std::fill becomes just a few assembly instructions, without a call at all.
  • Dai
    Dai about 2 years
    In .NET Framework 4.x, Array.Clear() is faster for N > ~75, but in .NET 6 I see that Array.Clear() is now faster for N > ~25.
  • Dai
    Dai about 2 years
    @Richard Array.Clear() is slower than for for very small arrays (1 <= N < ~25-75) though, owing to Array.Clear's internal logic for parameter validation and getting the dimensions/bounds of the array.