OLED Characters Drifting Over Time

I have a 128x64 Aliexpress I2c OLED wired up to my Arduino, what I'm observing is over time the characters will become kinda jumbled, and I'm trying to understand what exactly could be the cause of this.

You'll have to excuse my messy code, this is some deep into "will it work" testing right now.

See Images attached of what it it ends up looking like after I give it 10-30 seconds, that second line should say 59.94, and there's an entire line (similar to how it says FPS above 59.94) that should say SPEED above 1 PPF, that's completely disappeared after a little bit.

#include <Adafruit_GrayOLED.h>
#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>

#include <Adafruit_SSD1306.h>
#include <splash.h>

#include <SPI.h>
#include <Wire.h>

#define SCREEN_ADDRESS 0x3C

Adafruit_SSD1306 display(128, 64, &Wire, -1);


byte FPS = 7; // FPS Mode, options: 1 = 23, 2 = 24, 3 = 25, 4 = 29, 5 = 30, 6 = 50, 7 = 59, 8 = 60
byte SPEED = 1; // Pulse speed, 1 = 1 pulse per frame, 2 = 1 pulse per 10 frames, 3 = 1 pulse per second, 4 = 1 pulse per minute 
int B_Value; // Stores the active value of button array
String FPS_STRING;
String SPEED_STRING;

void setup() {
  Serial.begin(115200);

  pinMode(9, OUTPUT);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  display.clearDisplay();
  displayUpdate();
}

void loop() {
  
  // reads value of A1 button line and enters data into B_Value (0 - 1023)
  B_Value = analogRead(A1);
  Serial.println(B_Value);

  if (SPEED == 1) {
    SPEED_STRING = "1 PPF";
  }

  if (SPEED == 2) {
    SPEED_STRING = "1 PP 10-SEC";
  }

  if (SPEED == 3) {
    SPEED_STRING = "1 PPS";
  }

  if (SPEED == 4) {
    SPEED_STRING = "1 PPM";
  }

  if (SPEED == 5) {
    SPEED = 1;
  }

  if (B_Value >= 513) { //ranges between 513-1023 will increase SPEED mode
    SPEED++;
    displayUpdate();
  }

  if (FPS == 1) {
    FPS_STRING = "23.98";
  }

  if (FPS == 2) {
    FPS_STRING = "24";
  }

  if (FPS == 3) {
    FPS_STRING = "25";
  }

  if (FPS == 4) {
    FPS_STRING = "29.97";
  }

  if (FPS == 5) {
    FPS_STRING = "30";
  }

  if (FPS == 6) {
    FPS_STRING = "50";
  }

  if (FPS == 7) {
    FPS_STRING = "59.94";
  }

  if (FPS == 8) {
    FPS_STRING = "60";
  }

  if (FPS == 9) {
    FPS = 1;
  }

  if (B_Value <= 512 && B_Value > 20) { //ranges between 21-512 will increase FPS mode
    FPS++;
    displayUpdate();
  }
  
  tone();

}

void tone() {
  tone(9, 400); // Send 1KHz sound signal...
  delay(50);        // ...for 1 sec
  noTone(9);     // Stop sound...
  delay(5000);        // ...for 1sec
}

void displayUpdate() {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  display.println("FPS:");
  display.println(FPS_STRING);
  display.setCursor(0, 40);
  display.println("SPEED: ");
  display.println(SPEED_STRING);
  display.display();
}

The cause is you writing on the OLED in the same place that has been previously written.
When writing text, the code only sets the on pixels of what it is writing. So to change text you have to remove the old text first.
The simplest way is to clear the OLED and then write everything again, you can put that in your displayUpdate function.
However that causes flickering. So it is better to draw a black rectangle over the old text first. If you do this you will not have to keep writing the fixed text again, just the values that have changed. This will also make updating faster.

Try

display.setTextColor(WHITE, BLACK);

This will overwrite the background pixels, behind the text you are printing, with black, so you may not need to clear the area first. However, if the text you are printing has fewer characters, or you are using a proportional font, you may still see part of the old text left behind. It does not look like the font you are using is proportional, so if you pad all your text strings to the same length, that should fix the problem.