Better grid Performance


#1

Hello there,

I createt a scaleable grid, that have no funktion at the Moment.
But it is Scaleable and you can move it.

Now my problem.

I want to generate a Grid with 1000*1000 rectangles (or more), but 1 000 000 rectangles are very much.
If i want to scale or transform the grid, I have only about five FPS
Is there a way to make that I reach 30 FPS?

Down there is the Code.
Thank you very much.

// Szize of one rectangle
int  size = 50,t;
float s,tr, tx, ty, tix, tiy;
//Grid size
int x = 1000, y = 1000;

class Gitter{
 
 float numx, numy, size, col,mode,px,py,i;
//I need them later, but at the moment hey have no function
 int n1, n2, n3, n4, n5, n6, n7, n8, i2;
 
 Gitter(float id, float NUMX, float NUMY, float  SIZE){
   numx = NUMX;
   numy = NUMY;
   size = SIZE;
   i = id;   
 
 }
  
    void Draw(){
  rectMode(CENTER);
  noStroke();fill(255);rect (numx * size +10,numy * size + 10, size-1 , size-1 );
    }
}
Gitter[] gitter = new Gitter[x*y];


void setup(){
size(1600,800);
  
 
   int  I = 0;
  int ix,iy;
  s = 1;
  for (iy = 0;iy < y; iy = iy+1){
    for(ix = 0;ix < x; ix = ix+1){
      gitter[I] = new Gitter(I++,ix, iy, size);      
    }
  }
  tr = 0;
  
}
void draw(){

  
 //scaling andtranslations
  if (keyPressed){
      if (keyCode == UP ){
      s=s+0.05;
    }
     else if (keyCode == DOWN ){
       s=s-0.05;
    }
  }
  
  if ((mousePressed) && (mouseButton == LEFT)) {
    if (tr == 0){
      tr =  2;
      tix = tx;
      tiy = ty;
     tix = tix - mouseX*(1/s);
     tiy = tiy - mouseY*(1/s);
    }
    else{
      tx = (1/s)*mouseX + tix;
      ty = (1/s)*mouseY + tiy;
      
      tr = 3;
      
    }
  }
  if (tr > 0){
  tr = tr - 1;
  }
   
  scale(s);
translate(tx,ty);
  background(0);
  
  int ix,iy;int I=0;
  //draw grid
 for (iy = 0;iy < y; iy = iy+1){
    for(ix = 0;ix < x; ix = ix+1){
       gitter[I++].Draw();   
      
    }
 }
  
}

#2

If anyone have an idea, please let me here it

Maybe you ask yourself, why I want to create a grid like this.
That’s just training.
I have a lot of ideas for them I have to create more objects. Not rectangles, but different objects.
I hope, that I learn to understand, how I can create them without a large framedrop and without a loop, which have to run every time it called one million times


#3

why not play and make a benchmark list FPS ( print like

  void draw() {
  background(0);
  fill(255);
  text(nf(frameRate,1,1),10,10);
  • grid 100 500 1000
  • your program has the loop structure and the JOB: draw rect()

i see that when i disable the rect() in the class draw, FPS only get 80% ( 45 of 60FPS)…

  • change the canvas size has what effect…

a small thing can help, its a

void setup() {
  noSmooth();

i encourage you to test the limits of your hardware / OS and Processing,
but soon you might see that that Gigantomania
like your size(3000,2000) and grid 1000*1000
not really teach you coding, and that is what it is about here.


#4

Thank you very much, I will try it out


#5

@kll
An other idea, is it possible, that I just generate the rectangles, which I display at the moment?
I mean, that the program generates new rectangles, if I zoom out?


#6

now you do translate and scale ( move and zoom )
what is a killer if you want use like the color change click on rectangle
( i give you that code already but actually you go backward )

instead you can change x,y,w,h ( or even grid ) and regenerate the grid
after keypress

as i play with that i see already a problem,
a regeneration of the class array deletes also the knowledge of which one was clicked …
so for both ways need to separate the size and the clicked array


#7

@kll
And it teaches me coating in the point that I will learn, to work with much objects.
My later goal is, to create an small ai.
And for this I want to lern, how I generate a large number of objects like neurons, ais or anything like this, and how I can manage every object that uses the ai sepperately if I create more than one at the same time


#8

I saw your code and I understood how it worked, but my goal is not to create a large grid with one million rectangles, my goal is to learn, how I can work with one million objects how fast how possible.
I want to learn, If I should use sub programs and if yes why. The how is the other question, but why I should do this or something other and for what can I use something like a class and what not.


#9

now actually i doubt that you run my
example from

need to click on the

example

to see the code


#10

Use renderer FX2D for size(): :racing_car:
Processing.org/reference/size_.html


#11

@GoToLoop thank you, I will try it out.

@kll I ran your code and I found it great that the size of the rectangles scales with the size of the rows and the size of the screen.
But I am a beginner and I have to learn, that scaling isn’t the best idea.

And that is a very good idea and I want to try it out.
I think, that this is the solution for my grid.


#12

this version has changed moving and sizing

// https://discourse.processing.org/t/scalable-grid-with-rectangles/7256
// https://discourse.processing.org/t/better-grid-performance/7314
// test FPS on RPI
// grid 8     FPS 59
// grid 100   FPS 6.7  ( disable rect get FPS 45 )  ( noSmooth FPS 9 )
// grid 100   FPS 5.4  ( size(1200,1200) )
// grid 500   FPS go down slowly ?
// test FX2D not run on RPI


int x = 12, y = x, w = 5, h = w, grid = 100, many = grid*grid;
boolean auto = false;//true;
boolean shownum = false;    // key [n]
boolean showstroke = true; 
boolean showFPS = true;
// color setup:
color bg  = color(200, 200, 0);
color stk = color(0, 0, 200);
color fillsel = color(0, 200, 0);
color fillnsel= color(200, 0, 200);

Myrect[] myrects= new Myrect[many];

void setup() {
  size(800, 520);
  noSmooth();
  set_grid();
  println("use: mouse LEFT to select, mouse RIGHT to deselect");
  println("key UP DOWN RIGTH LEFT for position");
  println("key +  -  for grid size");
  println("key n toggle shownumber");
}

void draw() {
  background(bg);
  fill(0);
  if (showFPS ) text(nf(frameRate, 1, 1), 10, 10);
  for (int i = 0; i < many; i++) myrects[i].drawit();               // draw each rect ( and check on mouse over + click )
}

class Myrect {
  int x, y, id;//, w, h; from global
  boolean selected=false;
  Myrect (int x, int y, int id) {
    this.x = x; 
    this.y = y;
    this.id = id;
  }
  void drawit() {
    if ( showstroke ) stroke(stk); 
    else noStroke();
    if ( selected ) fill(fillsel);
    else            fill(fillnsel);
    rect(x, y, w, h);
    fill(0);   // black text
    if (shownum) text(id, x+w/4, y+h/3);
    sel();
  }
  boolean over() {
    return( x < mouseX && mouseX < x+w && y < mouseY && mouseY < y+h );
  }
  void sel() {
    if ( over() ) {
      if (  selected && mousePressed && mouseButton == RIGHT) selected=false;
      if ( !selected && mousePressed && mouseButton == LEFT)  selected=true;
    }
  }
}

void set_wh() {
  // use x,y,grid as master and auto adjust rectangles (w,h) to window:
  println(" width= "+width+", height= "+height+", grid= "+grid);
  w = ( width  - 2 * x ) / grid;   
  println(" w= "+w+", x= "+x+", ( grid * w + 2 * x )= "+(grid*w+2*x));
  h = ( height - 2 * y ) / grid;
  println(" h= "+h+", y= "+y+", ( grid * h + 2 * y )= "+(grid*h+2*y));
}

void set_grid() {
  if ( auto ) set_wh();
  for (int i = 0; i < many; i++)  myrects[i]=new Myrect(x+(i%grid)*w, y+(floor(i/grid))*h, i);
}

void keyPressed() {
  if ( keyCode == UP )         y--;
  else if ( keyCode == DOWN )  y++;
  else if ( keyCode == LEFT )  x--;
  else if ( keyCode == RIGHT ) x++;
  else if ( key     == '+' )   w++;
  else if ( key     == '-' )   w--;
  h=w;
  set_grid();

  if ( key == 'n' ) shownum = !shownum;
}


#13

Wow, I did not thought, that the scale and translation would effect the fps so massive. At home I will try it instantly.

Thank you very much


#14

i wait to see your test list,
this on top of the code relates to a 40euro computer with 1GB RAM ( for cpu gpu and ramdisk )

try with backup memory class just hold one boolean.

// https://discourse.processing.org/t/scalable-grid-with-rectangles/7256
// https://discourse.processing.org/t/better-grid-performance/7314
// test FPS on RPI
// grid 8     FPS 59
// grid 100   FPS 6.7  ( disable rect get FPS 45 )  ( noSmooth FPS 9 )
// grid 100   FPS 5.4  ( size(1200,1200) )
// grid 500   FPS go down slowly ?
// test FX2D not run on RPI

// use backup memory array for resize/reinit grid but remember selected rects

int x = 12, y = x, w = 10, h = w, grid = 50, many = grid*grid;
boolean auto = false;//true;
boolean shownum = false;    // key [n]
boolean showstroke = true; 
boolean showFPS = true;
// color setup:
color bg  = color(200, 200, 0);
color stk = color(0, 0, 200);
color fillsel = color(0, 200, 0);
color fillnsel= color(200, 0, 200);

Myrect[]   myrects   = new Myrect[many];
Mybackup[] myselects = new Mybackup[many];  // temporary memory

void setup() {
  size(800, 520);
  noSmooth();
  set_grid(true);     // init
  println("use: mouse LEFT to select, mouse RIGHT to deselect");
  println("key UP DOWN RIGHT LEFT for position");
  println("key +  -  for grid size");
  println("key n toggle shownumber");
}

void draw() {
  background(bg);
  fill(0);
  if (showFPS ) text(nf(frameRate, 1, 1), 10, 10);
  for (int i = 0; i < many; i++) myrects[i].drawit();               // draw each rect ( and check on mouse over + click )
}

class Mybackup {
  boolean selected=false;  
}

class Myrect {
  int x, y, id;//, w, h; from global
  boolean selected=false;
  Myrect (int x, int y, int id) {
    this.x = x; 
    this.y = y;
    this.id = id;
  }
  void drawit() {
    if ( showstroke ) stroke(stk); 
    else noStroke();
    if ( selected ) fill(fillsel);
    else            fill(fillnsel);
    rect(x, y, w, h);
    fill(0);   // black text
    if (shownum) text(id, x+w/4, y+h/3);
    sel();
  }
  boolean over() {
    return( x < mouseX && mouseX < x+w && y < mouseY && mouseY < y+h );
  }
  void sel() {
    if ( over() ) {
      if (  selected && mousePressed && mouseButton == RIGHT) selected=false;
      if ( !selected && mousePressed && mouseButton == LEFT)  selected=true;
    }
  }
}

void set_wh() {
  // use x,y,grid as master and auto adjust rectangles (w,h) to window:
  println(" width= "+width+", height= "+height+", grid= "+grid);
  w = ( width  - 2 * x ) / grid;   
  println(" w= "+w+", x= "+x+", ( grid * w + 2 * x )= "+(grid*w+2*x));
  h = ( height - 2 * y ) / grid;
  println(" h= "+h+", y= "+y+", ( grid * h + 2 * y )= "+(grid*h+2*y));
}

void set_grid(boolean init) {
  if ( auto ) set_wh();
  if ( init )  for (int i = 0; i < many; i++)  myselects[i]=new Mybackup();                     // init backup memory
  else         for (int i = 0; i < many; i++)  myselects[i].selected = myrects[i].selected;     // backup
  for (int i = 0; i < many; i++)  myrects[i]=new Myrect(x+(i%grid)*w, y+(floor(i/grid))*h, i);  // resize
  if ( !init ) for (int i = 0; i < many; i++)  myrects[i].selected = myselects[i].selected;     // restore
}

void keyPressed() {
  if ( keyCode == UP )         y--;
  else if ( keyCode == DOWN )  y++;
  else if ( keyCode == LEFT )  x--;
  else if ( keyCode == RIGHT ) x++;
  else if ( key     == '+' )   w++;
  else if ( key     == '-' )   w--;
  h=w;
  auto = false;  // confirm
  set_grid(false);

  if ( key == 'n' ) shownum = !shownum;
}


#15

The results of my test

image

//resolutions with scaling and transformation
//grid 10 * 10 = 60 fps
//grid 100 * 100 = 60 fps
//grid 200 * 200 = 56 fps
//grid 300 * 300 = 36 fps
//grid 400 * 400 = 21 fps
//grid 500 * 500 = 14 fps

//resolutions with scaling and transformation
//grid 10 * 10 = 60 fps
//grid 100 * 100 = 60 fps
//grid 200 * 200 = 58 fps
//grid 300 * 300 = 38 fps
//grid 400 * 400 = 24 fps
//grid 500 * 500 = 16 fps

//computer states 4k monitor, 2.6 Ghz CPU, 16 GB ram.





int  size = 3,t;
float rd, s,tr, tx, ty, tix, tiy;
//Grid size
int x = 500, y = 500;
boolean showFPS = true;
int ac;

class Gitter{
 
 float numx, numy, size, col,mode,px,py,i,ac;
//I need them later, but at the moment hey have no function
 int n1, n2, n3, n4, n5, n6, n7, n8, i2;
 
 Gitter(float id, float NUMX, float NUMY, float  SIZE, float acc){
   numx = NUMX;
   numy = NUMY;
   size = SIZE;
   i = id;  
   i2 = (int)id;
  ac = (int)acc;
   
 }
 
  
    void Draw(){
    
  rectMode(CENTER);
 
  
  tr = 0;
  if (gitter[i2].ac == 2) {fill(200);rect (numx * size +10,numy * size + 10, size-1 , size-1 );}
    }
    
    
}
Gitter[] gitter = new Gitter[x*y];


void setup(){
size(3000,2000);
  noSmooth();
 
   int  I = 0;
  int ix,iy;
  s = 1;
  
 
  for (iy = 0;iy < y; iy = iy+1){
    for(ix = 0;ix < x; ix = ix+1){
       rd = random(1,11);
      gitter[I] = new Gitter(I++,ix, iy, size,rd);      
    }
  }
  
  
}
void draw(){
background(0);
 
 //scaling andtranslations
 


  if (showFPS ) text(nf(frameRate, 1, 1), 10, 10);
  int ix,iy;int I=0;
  //draw grid
 for (iy = 0;iy < y; iy = iy+1){
    for(ix = 0;ix < x; ix = ix+1){
       gitter[I++].Draw();   
      
    }
 }
  fill(255);
  textSize(20);
  text(nf(frameRate,1,1),40,40);
  
  
}

There is a small different, but it isn’t large. The test was without stroke. The stroke have a massive influence on the Performance.
With stroke I got only 9 fps in a 500*500 Grid.
The biggest problem are the rectangles. If I only create them (as object) but do not Draw them, the results was 60 FPS up to 2000 *2000 and about 40 FPS for 5000, by 5000.
I tryed a little bit out and createt randomly only about 10 % of the rectangles and of cours, the Framerate was much higher.

So here is my resolution.
drawing rectangles needs much performance, the scale and the transform a little bit, the Stroke and the Window size needs much performance too.
If I want to create a net of rectangles which is scaleable and transormeable, I can create the whole net, but draw only the rectangles, which are in my field of fiew. That would garant the best Performance, because I wont see every time the whoole field and so I have not to draw oll rectangles.


#16

and
noSmooth();

but anyhow you understand already the difference
for computation / logic / program flow
and the drawing of lines… incl internal pixel mapping / coloring

what you now need to get a feeling for might be a
CALC JOB
like not drawing 1000 rectangles but doing 1000 add ( like matrix ) calculations instead…


#17

Yes, my next goal is, to create a AI, which find speciel designs in a small grid, to learn, how they (AIs) work.