Performance in comparison to Processing

I’m trying out the different creative coding frameworks - openFrameworks, Processing and p5.js in 2D/3D, and I’m surprised that Processing outperforms openFrameworks in 2D and 3D. I created a 2D sketch for all the platforms and this is the results I get:

Processing (P2D): 22 fps
openFrameworks: 13 fps
p5.js: 0.4 fps
Processing.py: 0.3 fps

Both openFrameworks and Processing are using OpenGL. It’s possible that I’m doing something wrong in C++. I am using references as much as possible instead of copying memory. I’m on a Mac. Below is my code:

ofApp.cpp:

void ofApp::setup(){
    ofBackground(255, 255, 255);
    
    for (int i = 0; i < numCircles; i++) {
        float x = ofRandom(padding, width - padding);
        float y = ofRandom(padding, height - padding);
        float radius = ofRandom(radiusRange[0], radiusRange[1]);
        ofVec2f velocity = ofVec2f(ofRandom(-velocityRange, velocityRange), ofRandom(-velocityRange, velocityRange));
        circles.push_back(Circle(x, y, radius, velocity));
    }
    
    ofTrueTypeFont::setGlobalDpi(72);
    font.load("verdana.ttf", 12);
}

void ofApp::update(){
    for (auto &circle1 : circles) {
        ofVec2f force;
        int count = 0;
        for (auto &circle2 : circles) {
            if (&circle1 != &circle2) {
                float distance = ofDist(circle1.position.x, circle1.position.y, circle2.position.x, circle2.position.y);
                if (distance <= circle1.radius + circle2.radius && distance > 0) {
                    ofVec2f direction = circle1.position - circle2.position;
                    direction = direction.normalize();
                    float strength = forceStrength * circle2.mass * circle2.velocity.length();
                    force += direction * strength;
                    count++;
                }
            }
        }
        
        if (count > 0) {
            force /= count;
        }
        circle1.applyForce(force);
        
        ofVec2f friction = circle1.velocity;
        friction *= -1;
        friction = friction.getNormalized();
        friction *= frictionStrength;
        circle1.applyForce(friction);
    }
    
    for (auto &circle : circles) {
        circle.update();
    }
}

void ofApp::draw(){
    // circles
    for (auto &circle : circles) {
        circle.draw();
    }
    
    // FPS
    char frameRateStr[255];
    sprintf(frameRateStr, "%f fps", ofGetFrameRate());
    ofSetColor(0, 0, 0);
    font.drawString(frameRateStr, 10, 15);
}

Circle::Circle(float x, float y, float pRadius, ofVec2f pVelocity) {
    position = ofVec2f(x, y);
    radius = pRadius;
    mass = M_PI * pow(radius, 2) * massFactor;
    velocity = pVelocity;
    acceleration = ofVec2f(0, 0);
    
    strokeCircle.circle(glm::vec2(0, 0), radius + (strokeWidth / 2));
    strokeCircle.setStrokeWidth(strokeWidth);
    strokeCircle.setColor(0);
    
    fillCircle.circle(glm::vec2(0, 0), radius);
}

void Circle::update() {
    velocity += acceleration;
    if (maxVelocity != -1 && velocity.length() > maxVelocity) {
        velocity.normalize();
        velocity *= maxVelocity;
    }
    position += velocity;
    acceleration *= 0;
    
    checkEdges();
}

void Circle::draw() {
    ofPushMatrix();
    ofTranslate(position.x, position.y);
    strokeCircle.draw();
    fillCircle.setColor(ofColor(135, 138,212));
    fillCircle.draw();
    ofPopMatrix();
}

void Circle::checkEdges() {
    if (position.x > width) {
        position.x = width;
        velocity.x *= -1;
    } else if (position.x < 0) {
        position.x = 0;
        velocity.x *= -1;
    }
    if (position.y > height) {
        position.y = height;
        velocity.y *= -1;
    } else if (position.y < 0) {
        position.y = 0;
        velocity.y *= -1;
    }
}

void Circle::applyForce(ofVec2f force) {
    acceleration += force / mass;
}

ofApp.h:

class Circle {
public:
    ofVec2f position, velocity, acceleration;
    float mass, radius;
    
    Circle(float x, float y, float radius, ofVec2f velocity);
    void draw();
    void update();
    void checkEdges();
    void applyForce(ofVec2f force);
    
private:
    ofPath strokeCircle;
    ofPath fillCircle;
};

class ofApp : public ofBaseApp{
public:
    void setup();
    void update();
    void draw();

    ofTrueTypeFont font;
    vector<Circle> circles;
};

can you put your code in a zip or on GitHub – there are variables that are missing like numCircles so it’s a little hard to compile this to see what you are seeing.

I can’t upload files to the forum but I’ve put it here. You will need to change Project.xcconfig to point to where your openFrameworks is installed

can you try compiling in release and not debug – in release I get about 45 fps – in debug it’s pretty slow. This sort of slow down in debug is common with a lot of accessing of vectors, etc.

a couple of thoughts about optimizing your code also –

(a) right now you are checking circle a vs b and circle b vs a –

 for (auto &circle1 : circles) {
        for (auto &circle2 : circles) {

you could only check a vs b since the distance is the same

for (int i = 0; i < circles.size(); i++){
for (int j = 0; j < i; j++){
// compare circles[i] vs circles[j]

(b) your code spends the most time with ofDist – maybe you can use ofDistSquared and avoid a square root

That was the issue - I’m now getting 55 fps.

Thanks for the optimisation tips.