diff --git a/src/components/system/Options.vue b/src/components/system/Options.vue
index 333cd32..e3a7d5d 100644
--- a/src/components/system/Options.vue
+++ b/src/components/system/Options.vue
@@ -26,6 +26,11 @@
                 :value="hideChallenges"
                 @change="toggleSettingsOption('hideChallenges')"
             />
+            <Toggle
+                title="Unthrottled"
+                :value="unthrottled"
+                @change="toggleSettingsOption('unthrottled')"
+            />
             <Toggle
                 title="Offline Production<tooltip display='Save-specific'>*</tooltip>"
                 :value="offlineProd"
@@ -75,7 +80,7 @@ export default defineComponent({
         };
     },
     computed: {
-        ...mapSettings(["showTPS", "hideChallenges", "theme", "msDisplay"]),
+        ...mapSettings(["showTPS", "hideChallenges", "theme", "msDisplay", "unthrottled"]),
         ...mapPlayer(["autosave", "offlineProd"]),
         paused() {
             return player.devSpeed === 0;
diff --git a/src/game/gameLoop.ts b/src/game/gameLoop.ts
index dec566e..627e12a 100644
--- a/src/game/gameLoop.ts
+++ b/src/game/gameLoop.ts
@@ -3,6 +3,7 @@ import modInfo from "@/data/modInfo.json";
 import Decimal, { DecimalSource } from "@/util/bignum";
 import { layers } from "./layers";
 import player from "./player";
+import settings from "./settings";
 import state from "./state";
 
 /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
@@ -107,6 +108,8 @@ function updateLayers(diff: DecimalSource) {
     });
 }
 
+let intervalID: number | null = null;
+
 function update() {
     const now = Date.now();
     let diff: DecimalSource = (now - player.time) / 1e3;
@@ -169,8 +172,22 @@ function update() {
     updateLayers(diff);
 
     player.justLoaded = false;
+
+    if (settings.unthrottled) {
+        requestAnimationFrame(update);
+        if (intervalID != null) {
+            clearInterval(intervalID);
+            intervalID = null;
+        }
+    } else if (intervalID == null) {
+        intervalID = setInterval(update, 50);
+    }
 }
 
 export default function startGameLoop(): void {
-    setInterval(update, 50);
+    if (settings.unthrottled) {
+        requestAnimationFrame(update);
+    } else {
+        intervalID = setInterval(update, 50);
+    }
 }
diff --git a/src/game/settings.ts b/src/game/settings.ts
index 5144834..b3255f8 100644
--- a/src/game/settings.ts
+++ b/src/game/settings.ts
@@ -12,7 +12,8 @@ const state = reactive<Settings>({
     showTPS: true,
     msDisplay: MilestoneDisplay.All,
     hideChallenges: false,
-    theme: Themes.Nordic
+    theme: Themes.Nordic,
+    unthrottled: false
 });
 
 const settingsHandler: ProxyHandler<Record<string, any>> = {
diff --git a/src/typings/settings.d.ts b/src/typings/settings.d.ts
index 567c98e..097e313 100644
--- a/src/typings/settings.d.ts
+++ b/src/typings/settings.d.ts
@@ -9,5 +9,6 @@ export interface Settings {
     msDisplay: MilestoneDisplay;
     hideChallenges: boolean;
     theme: Themes;
+    unthrottled: boolean;
     [index: string]: unknown;
 }