// ==UserScript== // @name Amazon Page Smoother // @namespace http://tampermonkey.net/ // @version 0.0.1 // @description Improves performance on Amazon pages by throttling background tasks and pausing off-screen iframe rendering. // @license Unlicense // @author VeleSila // @match https://www.amazon.com/* // @match https://www.amazon.co.jp/* // @match https://www.amazon.co.uk/* // @match https://www.amazon.es/* // @match https://www.amazon.fr/* // @match https://www.amazon.de/* // @match https://www.amazon.it/* // @match https://www.amazon.ca/* // @match https://www.amazon.com.au/* // @exclude */cart/* // @exclude */buy/* // @grant none // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/541871/Amazon%20Page%20Smoother.user.js // @updateURL https://update.greasyfork.icu/scripts/541871/Amazon%20Page%20Smoother.meta.js // ==/UserScript== (function() { 'use strict'; // --- Configuration --- const FOREGROUND_TICK_RATE_MS = 150; const BACKGROUND_TICK_RATE_MS = 2000; /** * Consolidates multiple setInterval calls into a single, more efficient loop. */ function initializeTimerThrottler() { if (window.self !== window.top) { return; // Only run in the top-level window } const nativeSetInterval = window.setInterval; const nativeClearInterval = window.clearInterval; let nextTaskId = 1; const scheduledTasks = {}; // Using a plain object for the task queue // Override the browser's default setInterval function window.setInterval = (callback, delay, ...args) => { if (typeof callback !== 'function') { // For non-function callbacks (e.g., strings), use the native function return nativeSetInterval(callback, delay, ...args); } const id = nextTaskId++; scheduledTasks[id] = { callback: () => callback(...args), delay: Math.max(delay || 0, FOREGROUND_TICK_RATE_MS), lastExecution: 0, }; return id; }; // Override the corresponding clearInterval function window.clearInterval = (id) => { if (scheduledTasks[id]) { delete scheduledTasks[id]; } else { nativeClearInterval(id); } }; const masterLoop = () => { const now = performance.now(); const tickRate = document.hidden ? BACKGROUND_TICK_RATE_MS : FOREGROUND_TICK_RATE_MS; for (const id in scheduledTasks) { const task = scheduledTasks[id]; if (now - task.lastExecution >= task.delay) { try { task.callback(); task.lastExecution = now; } catch (error) { console.error("Error in throttled task:", error); delete scheduledTasks[id]; // Remove faulty task } } } setTimeout(masterLoop, tickRate); }; // Start the master loop setTimeout(masterLoop, FOREGROUND_TICK_RATE_MS); } /** * Pauses rendering for iframes that are not currently visible on screen. */ function initializeIframeManager() { if (window.self !== window.top) { return; } const visibilityWatcher = new IntersectionObserver( (entries) => { for (const entry of entries) { entry.target.style.contentVisibility = entry.isIntersecting ? 'visible' : 'hidden'; } }, { root: null, threshold: 0 } ); const domWatcher = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE) { if (node.tagName === 'IFRAME') { visibilityWatcher.observe(node); } else { node.querySelectorAll('iframe').forEach(iframe => visibilityWatcher.observe(iframe)); } } } } }); const startManaging = () => { document.querySelectorAll('iframe').forEach(iframe => visibilityWatcher.observe(iframe)); domWatcher.observe(document.body, { childList: true, subtree: true }); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', startManaging, { once: true }); } else { startManaging(); } } // --- Script Execution --- initializeTimerThrottler(); initializeIframeManager(); })();