p5 sketch freezing every 2ish seconds

My p5.js sketch is freezing for a couple of frames every 2-3 seconds. I know p5 is not performant, but I feel like my sketch is optimized enough to not warrant this.

I think it may have to do with how the particles are handled when driving, so I used a particle pool, but that had no effect on performance. Here is my code

game.js:

const canvasSize = 400;
let car;

function setup() {
    frameRate(60);
    angleMode(RADIANS);
    createCanvas(canvasSize, canvasSize);
    noStroke();
    car = new Car(200, 200);     
}

function draw() {
    background(100, 100, 100);

    car.drawCar();
    car.drawGroundMarks();
    car.updatePoints();

    let turnDirection = 0;
    if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) {
        turnDirection = -1;  // Turn left
    }

    if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) {
        turnDirection = 1;   // Turn right
    }

    car.rotateCar(turnDirection);

    if (keyIsDown(UP_ARROW) || keyIsDown(87)) {
        car.accelerateCar(1);
    }

    if (keyIsDown(DOWN_ARROW) || keyIsDown(83)) {
        car.accelerateCar(-1);
    }
}

car.js:

class Car {
    constructor(x, y, width = 40, height = 20, rotation = 0, speed = 0.05) {
        this.carX = x;
        this.carY = y;
        this.carW = width;  
        this.carH = height;
        this.carSpeed = speed;
        this.carRotation = rotation;
        this.maxSpeed = 9;
        this.carAcceleration = createVector(0, 0);
        this.carVelocity = createVector(0, 0);
        this.carPoints = [];
        this.color = [255, 0, 0];
        this.maxTurnSpeed = radians(20);  
        this.turnSpeed = 0;              
        this.turnAcceleration = radians(1);
        this.friction = 0.98;  // Friction to slow down car

        this.groundMarks = [];
        this.particlePool = new ParticlePool(); // Create the particle pool

    }

    drawCar() {
        // Draw the car body

        if (this.carPoints.length == 0)
            return;

        fill(...this.color);
        beginShape();
        this.carPoints.forEach(point => vertex(point.x, point.y));
        endShape(CLOSE);

        //fill(0, 0, 0);
        //ellipse(this.carPoints[0].x, this.carPoints[0].y, 5, 5); //back left wheel
        //ellipse(this.carPoints[3].x, this.carPoints[3].y, 5, 5); //back right wheel
        //ellipse(this.carPoints[2].x, this.carPoints[2].y, 5, 5); //front right wheel
        //ellipse(this.carPoints[1].x, this.carPoints[1].y, 5, 5); //front left wheel
        
        let windshieldLeftPoint = createVector((this.carPoints[0].x*.25 + this.carPoints[1].x*.75), (this.carPoints[0].y*.25 + this.carPoints[1].y*.75));
        let windshieldRightPoint = createVector((this.carPoints[3].x*.25 + this.carPoints[2].x*.75), (this.carPoints[3].y*.25 + this.carPoints[2].y*.75));
        fill(180, 180, 255);
        beginShape();
        vertex(this.carPoints[2].x, this.carPoints[2].y);
        vertex(this.carPoints[1].x, this.carPoints[1].y);
        vertex(windshieldLeftPoint.x, windshieldLeftPoint.y);
        vertex(windshieldRightPoint.x, windshieldRightPoint.y);
        endShape();

    }

    drawGroundMarks() {
        // Draw active particles
        this.groundMarks.forEach((mark) => {
            mark.draw();
        });

        // Remove dead particles and return them to the pool
        this.groundMarks = this.groundMarks.filter((mark) => {
            if (mark.dead) {
                this.particlePool.release(mark); // Return dead particles to the pool
                return false;
            }
            return true;
        });

        //console.log(this.groundMarks.length);
    }

    updatePoints() {
        this.carVelocity.add(this.carAcceleration);
        this.carVelocity.limit(this.maxSpeed);
        
        // Apply friction to gradually slow down the car when no acceleration
        this.carVelocity.mult(this.friction);

        this.carX += this.carVelocity.x;
        this.carY += this.carVelocity.y;
        this.carAcceleration.mult(0); // Reset acceleration after each frame

        let halfW = this.carW / 2;
        let halfH = this.carH / 2;

        let p1 = createVector(-halfW, -halfH); 
        let p2 = createVector(halfW, -halfH);  
        let p3 = createVector(halfW, halfH);   
        let p4 = createVector(-halfW, halfH);  

        this.carPoints = [p1, p2, p3, p4];

        this.carPoints.forEach(point => {
            let x = point.x;
            let y = point.y;
            let cosA = cos(this.carRotation);
            let sinA = sin(this.carRotation);
            let rotatedPoint = createVector(x * cosA - y * sinA, x * sinA + y * cosA);
            let translatedPoint = rotatedPoint.add(createVector(this.carX, this.carY));
            point.set(translatedPoint.x, translatedPoint.y);
        });
    }

    accelerateCar(direction) {
        let forwardVelocityX = this.carSpeed * direction * cos(this.carRotation);
        let forwardVelocityY = this.carSpeed * direction * sin(this.carRotation);
        this.carAcceleration.add(createVector(forwardVelocityX, forwardVelocityY));
        
        // Get recycled particles from the pool instead of creating new ones
        if (frameCount % 5 !== 0)
            return;
        
        this.groundMarks.push(this.particlePool.get(this.carPoints[0].x, this.carPoints[0].y));
        this.groundMarks.push(this.particlePool.get(this.carPoints[3].x, this.carPoints[3].y));
    }

    rotateCar(direction) {
        if (direction !== 0) {
            this.turnSpeed += this.turnAcceleration * direction;
            this.turnSpeed = constrain(this.turnSpeed, -this.maxTurnSpeed, this.maxTurnSpeed);
        } else {
            this.turnSpeed *= 0.9;
        }

        // If the car is moving, allow rotation, else stop turning
        if (this.carVelocity.mag() > 0.1) {
            this.carRotation += this.turnSpeed * (this.carVelocity.mag() / this.maxSpeed); // More natural turning at speed
        }
    }
}

drift particle.js

class driftParticle {
    constructor(x, y) {
        this.reset(x, y);
    }

    reset(x, y) {
        this.x = x;
        this.y = y;
        this.timeAlive = 0;
        this.alpha = 255;
        this.dead = false; // Reset dead flag
    }

    draw() {
        if (this.dead) return;
        
        this.alpha = 255 - this.timeAlive * 2;
        if (this.alpha <= 0) {
            this.dead = true;
        }
        fill(50, 50, 50, this.alpha);
        ellipse(this.x, this.y, 3, 3);
        this.timeAlive++;
    }
}

particle pool.js

class ParticlePool {
    constructor() {
        this.pool = [];
    }

    get(x, y) {
        let particle;
        if (this.pool.length > 0) {
            particle = this.pool.pop(); // Reuse an old particle if available
            particle.reset(x, y); // Reset its position and state
        } else {
            particle = new driftParticle(x, y); // Create a new one if none available
        }
        return particle;
    }

    release(particle) {
        this.pool.push(particle); // Return particle to the pool for reuse
    }
}