Why P2D is slower than default renderer?

Why P2D is much slower than default renderer? Here is the number of bubbles makes the FPS slower than 30.

  • Default renderer: click 28 times(2800 bubbles)
  • P2D: click 3 times(300 bubbles)
  • P3D: click 55 times(5500 bubbles)

I don’t know why is this happened, did I use too much random functions in my code? Why P3D works well but P2D works so badly.

This is the code. SOMEBODY HELP!

Bubble[] bubbles = new Bubble[0];
int total = 0;

void setup() {
  size(800, 800, P2D);
  smooth();
}

void draw() {
  background(255);

  for (int i=0; i<bubbles.length; i++) { 
    bubbles[i].display();
    bubbles[i].ascend();
    bubbles[i].edge();
  }
   
  text("fps :"+frameRate, 20, 20);
}

void mouseClicked() {
  for (int i=0; i<100; i++) {
    Bubble b = new Bubble();
    bubbles = (Bubble[])append(bubbles, b);
  }
}

class Bubble {
  float x;
  float y;
  float r;
  float n;
  color c = color(random(255), random(255), random(255), random(255));
  float speed;

  Bubble() {
    x = random(width);
    y = height+r;
    r = random(2,6);
    speed = random(1, 4);
  }

  Bubble(float tempR) {
    x = random(width);
    y = height+r;
    r = tempR;
    speed = random(2, 6);
  }

  Bubble(float tempR, float tempS) {
    x = random(width);
    y = height+r;
    r = tempR;
    speed = tempS;
  }

  void display() {
    fill(c);
    stroke(100);
    strokeWeight(2);
    circle(x, y, 2*r);
  }

  void ascend() {
    x = x+random(-5, 5);
    y = y - speed;
  }

  void edge() {
    if (x<=r) {
      circle(x+width, y, 2*r);
    } else if (x>=width-r) {
      circle(x-width, y, 2*r);
    }

    if (y<=r&&y>=-r) {
      circle(x, y+height, 2*r);
      if (x<=r) {
        circle(x+width, y+height, 2*r);
      } else if (x>=width-r) {
        circle(x-width, y+height, 2*r);
      }
    } else if (y<=-r) {
      y = y+height;
    }
  }
}
1 Like

I simply dunno why the JAVA2D renderer would happen to be faster than the P2D 1! :man_shrugging:
But the king of performance is the FX2D renderer FYI: :crown:
size(800, 700, FX2D);


1 Like

The answer is quite simple - P2D and P3D use OpenGL which is very slow rendering lines and very fast at filling areas so change the display method in Bubble class to

  void display() {
    fill(c);
    noStroke();
    circle(x, y, 2*r);
  }

and P2D simply flies :slight_smile:

1 Like

That’s part of it, but this is also due to the implementation of line drawing in P2D which favours accuracy over performance. There’s a bit more info in Performance troubles in P2D that’s worth a read. There’s an out of date code branch somewhere based on that issue - keep meaning to try updating it for latest Processing.

It’s stroke weights higher than 1 that are particularly affected. The default stroke weight keeps to 60fps easy here.

Incidentally, another workaround with P2D is to do -

void display() {
  noStroke();
  fill(0);
  circle(x, y, 2*r+1);
  fill(c);
  circle(x, y, 2*r);
}
4 Likes

Thanks, the FX2D is truly the king!!!
Like Neilcsmith and Quark said, it is the stroke weight makes the difference. Particularly when stroke weight higher than 1(default stroke weight).
I did some test, this is the number of bubbles makes the FPS slower than 30 in diffrent renderer and stroke weight.

Renderer strokeWeight(2) strokeWeight(1) noStroke()
Default 3k 3k 9k
P2D 0.3k 7k 17k
P3D 5.5k 7k 17k
FX2D 100k 100k 250k
3 Likes

Great answer! Thanks!

This has been bugging me, because frankly I don’t believe the figures - I think there’s more to it. One thing to be aware of with JavaFX is that unlike the OpenGL pipelines it’s not single threaded. Something that has caused a whole lot of issues with a recent client project I did, and I think is behind those figures - they’re going to be different, but not that different.

With P2D and P3D all your calculations and rendering happen on the animation thread. With JavaFX, drawing calls are batched up, then another thread handles rendering asynchronously. I have a feeling your figures might be reflecting just the framerate of batching up the data, not actually rendering it to the screen. It’s likely JavaFX is just throwing some frames away.

Note also this from the Javadoc of the JavaFX GraphicsContext used by Processing -

Each call pushes the necessary parameters onto the buffer where they will be later rendered onto the image of the Canvas node by the rendering thread at the end of a pulse.

:sweat_smile: I’m just a beginner, don’t know much about the principles behind it.

When I test it, I set the for loop to increase 1000 bubbles a click. With other renderer, the animation soon get slower. FX2D just get stuck a while when I increase the bubbles, then the screen looks fluently as the animation runs beginning.

No problem! In general, if you get outlier figures, always question why. Like you did with P2D, and the issue linked before is probably the cause there.

With FX2D, why would it be so much different? The possible answer is always that you’re not measuring what you think you are. Unlike the other renderers, I don’t think Processing’s framerate value with FX2D is really the number of frames being rendered per second. For that I think you’d need to get the value directly from JavaFX itself, and offhand I can’t remember an easy way to do that.

1 Like