For different texture sizes, which is faster? SetPixel or SetPixels?

I happen to generate quite a few textures (of fairly small size; less than < 300 most of the time) and was just wondering if there was some significant difference in space or cost between using SetPixel and SetPixels?

int size = 300;
// No mip-maps because this is a 1-to-1 for the GUI usually
Texture2D texture = new Texture2D(size, size, TextureFormat.ARGB32, false);
for(int a = 0; a < size; a++) {
    for(int b = 0; b < size; b++) {
        texture.SetPixel(a, b, Color.white);
    }
}
// Down here I would actually change the texture (above makes a "blank" canvas)

And for SetPixels, it looks like:

int size = 300;
Texture2D texture = new Texture2D(size, size, TextureFormat.ARGB32, false);
Color[] colors = new Color[size * size];
for(int a = 0; a < Mathf.Pow(size, 2); a++) {
    texture.SetPixels(colors);
}
// Do stuff to change texture

So which is faster? Is there any significant difference between them, and when does it happen (in 1000x1000 texture sizes)?

EDIT: Tried benchmarking this and I found that SetPixel is actually slower than SetPixels even at 1x1 texture sizes. SetPixels32 is faster than SetPixels for any texture larger than 2x2.

SetPixel, size: 1, time: 0.003963776
SetPixels, size: 1, time: 0.0005910769
SetPixels32, size: 1, time: 0.0005298704

SetPixel, size: 100, time: 0.003605723
SetPixels, size: 100, time: 0.002427459
SetPixels32, size: 100, time: 0.001961112

SetPixel, size: 1000, time: 0.05630431
SetPixels, size: 1000, time: 0.2315033
SetPixels32, size: 1000, time: 0.1754332

EDIT 2: Wolfram actually benchmarked the functions and s/he is obviously better at benchmarking than me (benchmark noobs, unite!), so I’ll post those benchmarks in here…

                         4096x4096 512x512  64x64     8x8     1x1
SetPixel                     21.1s   20.0s  20.6s    19.9s   20.4s
SetPixels+fillArray           7.7s    7.5s   7.4s     7.9s   32.9s
SetPixels                     5.9s    5.3s   5.3s     5.7s   29.2s
SetPixels32                   1.8s    0.59s  0.62s    1.2s   34.1s
SetPixel:SetPixels           x3.6    x3.8   x3.9     x3.5    x0.7
SetPixel:SetPixels32        x11.5   x33    x33      x16.3    x0.6
SetPixels:SetPixels32        x3.22   x9.0   x8.5     x4.7    x0.9

The times when it makes sense to use SetPixel instead of SetPixels is if you’re only changing a relatively few individual pixels in different places, and you don’t want the overhead of getting an array, making a few changes in the array, then copying the array back.

Your second code example is wrong, you are assigning 90000 times the same pixel array to your texture, which doesn’t make sense.

To answer your question, SetPixel() will be significantly slower, possibly by an order of magnitude or more. You are setting each of the single pixels individually, 90000 times in total, calling a function that needs to access the texture data, compute the exact location of that pixel, and replace it, plus there is the loop overhead of 300x executing the inner loop.

On the other hand, SetPixels() is just one call, assinging the whole array, which can just memcopied into the texture data.

EDIT:

If your question is about how to best initialize the array, a compromize might be feasible: With your first approach you’ll need to execute a statement 90000x in two nested loops. With your second approach you’ll need to execute a statement 90000x (=filling the color array with its initial value (note, in your current code, the color will be black, since it is not initialized)).

Instead, the fastest method (*) will be to create a Color array of size 300, initialize that, and then call SetPixels 300 times, setting one row at a time:

for(int a = 0; a < size; a++)
    texture.SetPixels(0,a,size,1,colors);

(*) EDIT: After doing some benchmarks, you don’t gain anything by splitting the initialization into a “one row at a time” loop. So simply create a Color32[size*size] array, initialize it, and use a single call to texture.SetPixels32(). This will be fastest for most texture resolutions, as @Eric5h5 explained.