Arrays - Fastest way to fill em.

Hi all,

A question:

What’s the fastest way to fill/clear an int type array with the value 0 every frame?

Is it:

  1. Create a new int[] each frame?

  2. Keep a copy of a 0-filled array then use System.arrayCopy() to fill the destination array with the copy?

  3. Use Arrays.fill(dest, 0)?

  4. Or something else I haven’t thought of?

Thanks :slight_smile:

Definitely Arrays.fill. That’s what it’s designed for - fill an array.

Using new would look for space to allocate new memory (very slow + if you get one each frame, you run out of memory and the garbage collector must kick in), and using System.arraycopy requires both reading and writing to an array, whereas Arrays.fill only requires writing.

Indeed, Arrays.fill all the way.

On a vaguely related note.

back when I was doing J2ME work, 1 of the fastest ways to fill an array was something like this :-

public static void fill(int [] array, int value)
{
   int length = Math.min(array.length,16);
   for(int i=0; i< length;i++)
   {
      array[i] = value;
   }
   
   while(length<<1 < array.length)
   {
      System.arraycopy(array,0,array,length,length);
      length<<=1;
   }
   
   System.arraycopy(array,0,array,length,array.length-length);
}

Crazy realy :smiley:

infact, on 1 phone in particular, due to a bug in arraycopy,
(it never made a copy of the src array when src=dst) the fastest way to fill an array was :-

public static void fill(int [] array, int value)
{
   array[0] = value;
   System.arraycopy(array,0,array,1,array.length-1);
}

None of this is useful, but its interesting none-the-less :wink:

[quote]Indeed, Arrays.fill all the way.
[/quote]
Hmm, thanks.

I was afraid that Sun’s implementation of Arrays.fill() would be something like this:

for(int i=0; i < array.length; i++)
   array[i] = 0;

I’m not sure exactly what optimizations the compiler would perform on such a loop but my guess is that it would not be as optimized as using the natively implemented System.arrayCopy().

The reason I’m looking for a fast way to fill an array with 0’s is because I want to clear the DataBuffer array of an image I’m fiddling around with (this is somewhat related to my earlier BufferedImage question, Abuse :wink: ).

Since I’m only going to animate/consider some pixels in the array each frame, I’ll have to clear the array first.

That’s almost exactly what it looks like, except much more flexible (i.e. more params, slower ???)… :frowning:

That’s probably as fast as it gets without JNI.

I suspect Array.fill is ‘known’ to the VM and it is optimized into very efficient native code. Just like the Math functions are really just placeholders for the VM to fill in with native instructions when it compiles the bytecode.

If the “state of the art” JVM can’t optimise that for loop and array fill into the tightest possible machine code by now, I’ll get me coat.

Cas :slight_smile:

I never knew the Math functions were optimized like that…I oughtta stop looking @ the source because it is fake!!! >:(

[I guess I should also stop trying to reimplement Math functionality :-/]

Regarding that J2ME for loop - first, I believe it would be faster to do a:


for(int i = array.length - 1; i >= 0; i--) array[i] = somevalue;

Thats what I have read on Sony ericsson slides. Another interesting thing I read was that due to the way exceptions are being handled on a J2ME platform, this should be a bit faster too:


try {

 int i = 0;
 while(true) {

  array[i++] = somevalue;
 }
} catch(Exception ArrayOutOfBoundsException e) { }

I may be wrong, but I may be right :slight_smile: And again, this (aspecially the last one) applies to J2ME, the first one to J2SE but is more ugly than effective.

That is an absolute abomination.

Cas :slight_smile:

I did a quick test and on the client your 1st method is as fast as a regular


        for (int i = 0; i < array.length; i++)
            array[i] = somevalue;

On the server, both your 1st method and the regular method are ~3 times as fast as the client.
Array.fill() is about as fast a loop in the client, in the server its a bit slower than a loop.
Your last method is (not surprisingly) waaaay slower in all tests. It’s just weird it is faster on J2ME…

But as usual, don’t take these numbers too seriously. They might only apply to my limited test case.

How much warmup did you do? We were seeing last week that with 1.4.2_04 we needed at least 5 minutes of continual stress to have given the server time to catch up with the client. And it could take ten minutes to get the full oomph. Although…that was with “real world” code that’s a lot less trivial than a stupid array fill.

(who cares?; please…show me the profiler output that claims array.fill is bottlenecking your application performance! and if the OP can’t, they are a FOOL [1] for even caring if there’s anything “faster”)

[1] - pre-emptive optimization being the root - if not “of all evil” - then at least of many optimization problems, and very very many bugs and broken code.

Yeah I edited my post after doing some more tests (where I just let the program run longer). In the server it’s still a tiny bit slower. Not really worth it, but still slower.

Sure, I’ve learned my lessons in the past which is why I added the disclaimer in my post that you shouldn’t take the results too seriously.

[quote]Yeah I edited my post after doing some more tests (where I just let the program run longer). In the server it’s still a tiny bit slower. Not really worth it, but still slower.
[/quote]
:frowning: Benchmarking still requires tons of patience, doesn’t it? Even with some fairly good free automated test tools appearing these days…

I get the impression that most of the crappy micro-benchmarkers who write all these silly specious articles on “java slower than C++ shocker” compound their mistakes by never running benchmarks for more than the minimum they reckon they need - typically about 30 seconds, or pehaps a few minutes if they’re feeling diligent. We certainly have seen improvements even 10 minutes after startup - and time when the server is “idling” seems to always be at 0% cpu usage, implying it’s only ever optimizing if there’s at least some load [blah imagines a benchmarker starting their app and leaving it idle for 30 minutes thinking this will “warm up” the server JVM].

Although, I guess I ought to be pleased if they ever even realise to try the server JVM ::slight_smile:

Speaking of which, does Sun not have a “tiger-team” in their marketing dept who seeks out and destroys broken benchmarks? It’s the kind of thing that MS inadvertently taught to all the big IT companies years ago - making it someone’s day-job to (legitimately) get rid of bad press is a very effective way of improving your reputation among customers. Given that a few accidentally broken benchmarks can cost you hundreds of thousands of dollars, as the bad-mouthing percolates…

[quote]percolates
[/quote]
hmmmmmmmmmm.

I just benchmark on the server VM to see how much of an impact it has for us being tied to the client VM (since nobody has the server VM).
Sometimes the impact is very high (array access being a notable example), sometimes the client performs surprisingly well compared to the server.
Now an IBM-like VM would be nice :-), having server speed and client warm-up time all in one.

I ran a test comparing two methods on a J2ME emulator:

Method 1:


for(int i = 0; i < array.length; i++) array[i] = i;

Method 2:


int i = 0;
            
try {

 while(true) array[i++] = i;
} catch(Exception e) { }

After a few hundred tests (didnt really believe it myself after just a few tests) I got this result on 10000 elements in a int[]:

1: 150 ms
2: 80 ms

So apparently I was right about the ugly method 2 being faster. Now the question remains if it is faster to do a “i != 0” comparison rather than doing a “i < b” comparison, my argument was that doing a “!= 0” would only need one memory reference, while the second would need two. But erik said it wouldnt matter since of the pipeline architecture and since I am not an expert when it comes to hardware perhaps someone has somethint to say about this?

Hey, don’t quote me on that! I said my asm was rusty and this is just an assumption :wink: ;D
Anyway I never seen any speed difference between a!=0 and a<b.

Ok, I take that back :slight_smile: