processingdrawslowdown

my code is slow and I have no idea how to fix it?


I'm making a program that you can draw in and when there are more than 38000 _points it starts to lag.

here's the code:

public class _point {
  float x = 0;
  float y = 0;

  boolean active = true;

  color c = color(255, 255, 255);

  public void _point() {
  }
  public void change_pos(float x1, float y1, color c1)
  {
    x = x1;
    y = y1;
    c = c1;
  }
  public void u_line(float px, float py)
  {
    if (dist(x, y, px, py) < 15)
    {
      stroke(c);
      strokeWeight(5);
      line(x, y, px, py);
    }
  }
  public void remove_beans()
  {
    if (eraser) {
      if (dist(x, y, mouseX, mouseY)<main_tool.radius/2) {
        active = false;
      }
    }
  }
  public void a_line()
  {
    for (int i = 0; i < _points.size(); ++i) {
      _point part = _points.get(i);

      if (dist(x, y, part.x, part.y) < 15)
      {
        line(x, y, part.x, part.y);
      }
    }
  }
}

and where its drawn:

ArrayList<_point> _points = new ArrayList<_point>();
void draw_beans() {
  for (int i = 0; i < _points.size(); ++i) {
    _point part = _points.get(i);

    if (part.active == false) {
      _points.remove(i);
    }

    if (i != 0 && i != _points.size()-1 && i != _points.size()) {
      OPTIMIZE(_points.get(i+1), part, _points.get(i-1));
    }

    if (i != 0) {
      _point past = _points.get(i-1);

      part.u_line(past.x, past.y);//past.x,past.y
    }
  }
}

this is were the points are added to the array:

void add_beans() {
  if (!eraser && !IIIINNZ()) {
    _points.add(new _point());
    _point part = _points.get(_points.size()-1);
    part.change_pos(mouseX-transX, mouseY-transY, color(int(color_text0.texts), int(color_text1.texts), int(color_text2.texts)));
  }
  for (int i = 0; i < _points.size(); ++i) {
    if (eraser && !IIIINNZ()) {
      _point part = _points.get(i);
      part.remove_beans();
    }
  }
}

and an optimization:

void OPTIMIZE(_point next, _point thiss, _point prev) {
  if (dist(thiss.x, thiss.y, next.x, next.y)+dist(thiss.x, thiss.y, prev.x, prev.y)<14) {
    thiss.active = false;
  }
}

setup:

void setup() {
  size(512, 512);
  noCursor();
}

draw:

void draw() {
  background(#222833);//27,27,33
  textFont(font);

  pushMatrix();
  translate(transX, transY);
  draw_beans();
  popMatrix();

  show_options();

  main_tool.update();

  println(_points.size());
}

I have tried to multithread it but the thread doesn't align with the animation thread so there are missing points.

I am using the Processing 3 java library and vscode.


Solution

  • It's unclear what OPTIMIZE and IIIINNZ do.

    Without being able to run your code and test I can't tell if those function slow it down or is it simply the (re)rendering.

    I advise using VisualVM to Profile the CPU usage of your sketch(PApplet subclass). The CPU Profiler will list the methods from the slowest: VisualVM CPU Profiler

    Focus your efforts on the top slowest and try not to sacrifice code readability if possible.

    (On code readability I recommend using a Java Style guide overall. It will save time scanning/reading longer and longer programs)

    Your question reminds me a little bit of an older one I answered a while ago.

    It's similar because of the many lines rendered. In addition yours uses distance() (which in turn uses Math.sqrt() which can cost the CPU a bit, but as much as rendering. You could use squared distance instead, but that will make the code a bit harder to read and if compared to rendering isn't that slow I'd leave that in).

    Essentially there are many point instances that render lines based on threshold distances. Each stroke(), strokeWeight(), line() call will have it's cost.

    I've tried to group line rendering into something simpler: a single shape accessing all the point instances:

    void draw_beans() {
      beginShape(LINES);
      for (int i = 0; i < points.size(); ++i) {
        Point part = points.get(i);
        
        
        if (part.active == false) {
          points.remove(i);
        }
    
        //if (i != 0 && i != points.size()-1 && i != points.size()) {
        //  OPTIMIZE(points.get(i+1), part, points.get(i-1));
        //}
    
        if (i != 0) {
          Point past = points.get(i-1);
    
          //part.u_line(past.x, past.y);//past.x,past.y
          vertex(past.x, past.y);
        }
      }
      endShape();
    }
    

    This barely made a dent and even if it would've been waaay faster it would've been limiting.

    It's worth baring in mind how line() is implemented behind the hood for each renderer. Surprisingly, the FX2D renderer might work better for your setup (e.g. size(512, 512, FX2D);)