We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › optimizing an ArrayList
Page Index Toggle Pages: 1
optimizing an ArrayList (Read 906 times)
optimizing an ArrayList
Apr 14th, 2010, 10:41pm
 
I am working with an ArrayList for the first time.  The following code really slows things down.  I am assuming this is due to the sheer number of objects being created.  

Is there a better method to achieve the effect I am looking for?

Thanks,
TB

Code:

ArrayList signals = new ArrayList();

void setup() {
 size(600,400);
 frameRate(20);
 colorMode(HSB,360,100,100,100);
 smooth();
 noStroke();
}

void draw() {
 background(0,0,100);
 for (int i = 0; i < signals.size(); i++){
   
   Circle currentCirc = (Circle) signals.get(i);
   currentCirc.update();
   
   if (currentCirc.finished()) {
     signals.remove(i);
   }

 }
 int col = round( random(0,360) );
 signals.add(new Circle(mouseX,mouseY,3,col));

}

void keyPressed(){
 signals.clear();
}


class Circle {
 float xPos;
 float yPos;
 float circSize;
 float growth;
 float circColor;

 Circle(float xPos, float yPos, float growth, float circColor) {
   this.xPos = xPos;
   this.yPos = yPos;
   this.growth = growth;
   this.circColor = circColor;
 }

 void update() {
   fill(circColor,100,100);
   ellipse(xPos,yPos,circSize,circSize);
   circSize += growth;
 }
 
 boolean finished(){
   if(circSize > width){
    return true;
   } else {
   return false;
   }  
}
 
}

Re: optimizing an ArrayList
Reply #1 - Apr 15th, 2010, 1:27am
 
Hi there..so this has nothing to do with ArrayList or the number of objects you create, it's a pretty small list (202).  Your issue is the fill rate, and apologies if you already get this.  

At peak, which is 202 ellipses the largest of which is as wide as the screen, you are drawing 18.9 million pixels per frame (per update())..that's a lot.  It's the same as filling the whole screen with a single color 79 times an update().

You can't increase fill rate as this is graphics card (and Core) dependent.  But you can do some things to get around the problem.  You can render in OpenGL which for this app is way faster but not as nice to look at.  Or you could set noFill() and just render the circle outlines.

So it's the amount of pixels or screen real estate that is your limiting factor not the arraylist nor the amount of things rendered.  

A real easy way to check this is to print out the FPS to the command line

String stuff = "FPS "+round(frameRate)+ "";
println(""+stuff+"");

Then move the mouse to the edge of the app when it is running.  You will see the FPS begin to increase back to 20, you still have the same size arraylist and you are still drawing 202 ellipses, but you are not drawing all the pixels that are off screen.

hope this helps..

nik
Re: optimizing an ArrayList
Reply #2 - Apr 15th, 2010, 1:44am
 
Slow in what sense? Compared to what? Your frame rate is low, it is normal to see the sketch quite slow.
[EDIT] Just see nikp's analysis, excellent. He is right, the sketch is slow as the frame rate isn't as high as it should be. Not much to do on this, as he said, but the ArrayList is certainly not the culprit! Smiley

Notes: avoid do delete an element of a collection while iterating on it with a classical for loop. Here it isn't critical as the grow rate is the same for all circles, so that's always the last one disappearing, but with random rates, for example, you can go for a surprise...
Here is a better way to handle deletion:
Code:
ArrayList signals = new ArrayList();

void setup() {
 size(600, 400);
 frameRate(20);
 colorMode(HSB, 360, 100, 100, 100);
 smooth();
 noStroke();
}

void draw() {
 background(0, 0, 100);
 for (int i = 0; i < signals.size(); i++) {
   Circle currentCirc = (Circle) signals.get(i);
   currentCirc.update();
 }
 for (int i = signals.size() - 1; i >= 0; i--) {
   Circle currentCirc = (Circle) signals.get(i);
   if (currentCirc.finished()) {
signals.remove(i);
   }
 }
 int col = round( random(0, 360) );
 signals.add(new Circle(mouseX, mouseY, 3, col));
 if (frameCount % 20 == 0)
 {
   println(second() + " - " + signals.size());
 }
}

void keyPressed(){
 signals.clear();
}


class Circle {
 float xPos;
 float yPos;
 float circSize;
 float growth;
 float circColor;

 Circle(float xPos, float yPos, float growth, float circColor) {
   this.xPos = xPos;
   this.yPos = yPos;
   this.growth = growth;
   this.circColor = circColor;
 }

 void update() {
   fill(circColor, 100, 100);
   ellipse(xPos, yPos, circSize, circSize);
   circSize += growth;
 }
 
 boolean finished(){
   return circSize > width;
 }
 
}

Note I loop in reverse order to ensure indexes remain valid (if you delete item n, item n+1 becomes item n and so on).
Note also the simplified finished() test... Smiley

I can't resist, I show the code using Java 1.5 syntax, as allowed by the release 0182 (not yet fully official):
Code:
// Typed ArrayList, can contain only Circle now
ArrayList<Circle> signals = new ArrayList<Circle>();

void setup() {
 size(600, 400);
 frameRate(20);
 colorMode(HSB, 360, 100, 100, 100);
 smooth();
 noStroke();
}

void draw() {
 background(0, 0, 100);
 // New for loop syntax
 for (Circle currentCirc : signals) {
   currentCirc.update();
 }
 for (int i = signals.size() - 1; i >= 0; i--) {
   // No need for cast anymore!
   Circle currentCirc = signals.get(i);
   if (currentCirc.finished()) {
signals.remove(i);
   }
 }
 int col = round( random(0, 360) );
 signals.add(new Circle(mouseX, mouseY, 3, col));
 if (frameCount % 20 == 0)
 {
   println(second() + " - " + signals.size());
 }
}
Re: optimizing an ArrayList
Reply #3 - Apr 15th, 2010, 12:25pm
 
actually, you can use iterators even in Java 1.4 syntax, although the syntax is quite inconvenient:

Code:

List signals = new LinkedList();
for (int it = list.iterator(); it.hasNext(); ) {
Circle currentCirc = (Circle) it.next();
}


this is primarily for iterating LinkedList, since otherwise you will be invoking LinkedList's worse case behavior if you use .get().
Page Index Toggle Pages: 1