How to improve WebGL batch render speed

I am writing a small sprite sheet renderer in WebGL, where I render quad with set with and height then I take one big sprite sheet and use the texture coordinates to pick what sprite should be shown on what quad. I do this all in one big object with position and texture coordinates array where i push new items in. I’m also using TWGL library to make WebGL a bit less verbose. Currently this system of batching items into one draw per frame isn’t working that well, how can it be improved?

class Render {

  constructor(selector) {
    this.vertexShaderSource = `#version 300 es
    in vec2 position;
    in vec2 texcoord;

    uniform vec2 u_resolution;

    out vec2 v_texCoord;

    void main() {
      vec2 zeroToOne = position / u_resolution;

      vec2 zeroToTwo = zeroToOne * 2.0;

      vec2 clipSpace = zeroToTwo - 1.0;

      gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);

      v_texCoord = texcoord;
    }`;

    this.fragmentShaderSource = `#version 300 es
    precision highp float;

    uniform sampler2D u_image;

    in vec2 v_texCoord;

    out vec4 outColor;

    void main() {
      outColor = texture(u_image, v_texCoord);
    }`;

    this.bufferInfo;
    this.gl = document.querySelector(selector).getContext("webgl2");
    this.programInfo = twgl.createProgramInfo(this.gl, [this.vertexShaderSource, this.fragmentShaderSource]);
    this.textures = [];
    this.uniforms = {
      u_resolution: [innerWidth, innerHeight],
      u_image: null,
    }

    this.arrays = {
      position: [],
      texcoord: [],
    };

    this.gl.canvas.width = innerWidth;
    this.gl.canvas.height = innerHeight;
  }

  loadImage(url, callback) {
    const texture = twgl.createTexture(this.gl, { src: url, mag: this.gl.NEAREST }, () => { callback ? callback() : "" });
    this.textures.push(texture);
    return {
      texture: texture,
      index: this.textures.length - 1
    };
  }

  clearBuffer() {
    this.arrays.position = [];
    this.arrays.texcoord = [];
  }

  setTexture(texture) {
    this.uniforms.u_image = texture;
  }

  addQuad(x, y, width, height, srcWidth, srcHeight, srcX, srcY, realWidth, realHeight) {
    const x1 = x;
    const x2 = x + width;
    const y1 = y;
    const y2 = y + height;

    this.arrays.position.push(
      x1, y1, 0,
      x2, y1, 0,
      x1, y2, 0,
      x1, y2, 0,
      x2, y1, 0,
      x2, y2, 0,
    );

    this.arrays.texcoord.push(
      srcX / srcWidth / 1, srcY / srcHeight / 1,
      (srcX + realWidth) / srcWidth / 1, srcY / srcHeight / 1,
      srcX / srcWidth / 1, (srcY + realHeight) / srcHeight / 1,
      srcX / srcWidth / 1, (srcY + realHeight) / srcHeight / 1,
      (srcX + realWidth) / srcWidth / 1, srcY / srcHeight / 1,
      (srcX + realWidth) / srcWidth / 1, (srcY + realHeight) / srcHeight / 1,
    );
  }

  setBuffer() {
    this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, this.arrays);
  }

  resizeCanvas() {
    twgl.resizeCanvasToDisplaySize(this.gl.canvas);
    this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
  }

  render() {
    this.gl.useProgram(this.programInfo.program);
    twgl.setUniforms(this.programInfo, this.uniforms);
    twgl.setBuffersAndAttributes(this.gl, this.programInfo, this.bufferInfo);
    twgl.drawBufferInfo(this.gl, this.bufferInfo);
  }
}

const render = new Render("#game");
const texture = render.loadImage("https://i.imgur.com/TQnyNHU.png", () => {

    requestAnimationFrame(renderStuff);

    render.resizeCanvas();
    
    function renderStuff() {
        render.clearBuffer();
        render.setTexture(texture);
        for(let y = 0; y < 100; y++) {
          for(let x = 0; x < 100; x++) {
          render.addQuad(x * 48, y * 48, 48, 48, 512, 512, 32, 0, 16, 16);
          }
        }
        render.setBuffer();
        render.render();

        requestAnimationFrame(renderStuff);
    }
});
* {
    margin: 0px;
    padding: 0px;
}

body, html {
    width: 100%;
    height: 100%;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twgl.js/4.19.5/twgl.min.js"></script>
    <script src="main.js" type="module" defer></script>
    <link rel="stylesheet" href="style.css">
    <title>Prometeus</title>
</head>

<body>
    <canvas id="game"></canvas>
</body>

</html>