kinetic-slider
Version:
A WebGL-powered kinetic slider component using PIXI.js
1 lines • 16 kB
Source Map (JSON)
{"version":3,"file":"FrameThrottler.cjs","sources":["../../../src/managers/FrameThrottler.ts"],"sourcesContent":["// src/components/KineticSlider/managers/FrameThrottler.ts\n\n/**\n * @file FrameThrottler.ts\n * @description Provides advanced frame timing controls to optimize rendering performance.\n * Offers various throttling strategies to consolidate updates and reduce GPU load.\n */\n\n/**\n * Frame throttling strategies that determine how updates are scheduled.\n * @enum {string}\n */\nexport enum ThrottleStrategy {\n /**\n * Fixed frames per second - aims for consistent frame timing\n * by enforcing a fixed interval between frames.\n */\n FIXED_FPS = 'fixed_fps',\n\n /**\n * Adaptive - adjusts timing based on device performance\n * by monitoring actual frame rates and adjusting accordingly.\n */\n ADAPTIVE = 'adaptive',\n\n /**\n * Priority-based - only throttles lower priority updates\n * while allowing high-priority updates to bypass throttling.\n */\n PRIORITY = 'priority',\n\n /**\n * None - no throttling applied (use with caution)\n * as it may lead to performance issues on low-end devices.\n */\n NONE = 'none'\n}\n\n/**\n * Configuration options for the FrameThrottler.\n * @interface ThrottlerConfig\n */\nexport interface ThrottlerConfig {\n /**\n * Target frames per second (for FIXED_FPS strategy).\n * Higher values provide smoother animation but require more processing power.\n */\n targetFps?: number;\n\n /**\n * Minimum acceptable frames per second (for ADAPTIVE strategy).\n * The throttler will attempt to maintain at least this frame rate.\n */\n minFps?: number;\n\n /**\n * Maximum acceptable frames per second (for ADAPTIVE strategy).\n * The throttler will cap the frame rate at this value to save resources.\n */\n maxFps?: number;\n\n /**\n * Selected throttling strategy to use.\n * @see {ThrottleStrategy}\n */\n strategy?: ThrottleStrategy;\n\n /**\n * Enable performance monitoring and auto-adjustment.\n * When enabled, the throttler will collect metrics and adjust settings dynamically.\n */\n enableMonitoring?: boolean;\n}\n\n/**\n * Default configuration values for the throttler.\n * @type {ThrottlerConfig}\n */\nconst DEFAULT_CONFIG: ThrottlerConfig = {\n targetFps: 60,\n minFps: 30,\n maxFps: 120,\n strategy: ThrottleStrategy.FIXED_FPS,\n enableMonitoring: true\n};\n\n/**\n * Performance data for monitoring and auto-adjustment.\n * @interface PerformanceData\n * @private\n */\ninterface PerformanceData {\n /**\n * Array of recent frame durations in milliseconds.\n * Used to calculate average performance over time.\n */\n frameTimes: number[];\n\n /**\n * Current average FPS calculated from recent frame times.\n */\n currentFps: number;\n\n /**\n * Number of frames processed since initialization.\n */\n frameCount: number;\n\n /**\n * Timestamp of last performance adjustment in milliseconds.\n */\n lastAdjustment: number;\n\n /**\n * Current throttle interval in milliseconds.\n */\n currentInterval: number;\n}\n\n/**\n * Manages frame timing and throttling for optimal performance.\n * This class helps reduce GPU load by controlling when frames are processed.\n */\nexport class FrameThrottler {\n /** Active configuration */\n private config: ThrottlerConfig;\n\n /** Performance monitoring data */\n private performance: PerformanceData;\n\n /** Timestamp of the last processed frame */\n private lastFrameTime: number = 0;\n\n /**\n * Create a new FrameThrottler with the specified configuration.\n *\n * @param {ThrottlerConfig} [config] - Configuration options for the throttler\n *\n * @example\n * // Create a throttler with default settings (60fps, FIXED_FPS strategy)\n * const throttler = new FrameThrottler();\n *\n * @example\n * // Create a throttler with custom settings\n * const throttler = new FrameThrottler({\n * targetFps: 30,\n * strategy: ThrottleStrategy.ADAPTIVE,\n * minFps: 15,\n * maxFps: 60\n * });\n */\n constructor(config?: Partial<ThrottlerConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n\n // Initialize performance data\n this.performance = {\n frameTimes: [],\n currentFps: this.config.targetFps!,\n frameCount: 0,\n lastAdjustment: performance.now(),\n currentInterval: this.calculateInterval(this.config.targetFps!)\n };\n\n this.lastFrameTime = performance.now();\n }\n\n /**\n * Calculate the frame interval in milliseconds from FPS.\n *\n * @param {number} fps - Frames per second\n * @returns {number} Interval in milliseconds between frames\n * @private\n */\n private calculateInterval(fps: number): number {\n return 1000 / fps;\n }\n\n /**\n * Check if enough time has passed to process the next frame.\n *\n * @param {number} [priority] - Optional priority level to consider (higher values bypass more throttling)\n * @returns {boolean} True if the frame should be processed, false if it should be skipped\n *\n * @example\n * // Basic usage in animation loop\n * if (throttler.shouldProcessFrame()) {\n * // Process frame\n * render();\n * throttler.frameProcessed();\n * }\n *\n * @example\n * // Usage with priority (3 is highest priority)\n * if (throttler.shouldProcessFrame(2)) {\n * // Process high-priority frame\n * renderImportantElements();\n * throttler.frameProcessed();\n * }\n */\n public shouldProcessFrame(priority?: number): boolean {\n const now = performance.now();\n const elapsed = now - this.lastFrameTime;\n\n // Handle different strategies\n switch (this.config.strategy) {\n case ThrottleStrategy.NONE:\n return true;\n\n case ThrottleStrategy.PRIORITY:\n // High priority updates bypass throttling\n if (priority !== undefined && priority >= 2) {\n return true;\n }\n // Otherwise use fixed fps throttling\n return elapsed >= this.performance.currentInterval;\n\n case ThrottleStrategy.ADAPTIVE:\n // Adaptively adjust the interval based on recent performance\n this.updateAdaptivePerformance(now);\n return elapsed >= this.performance.currentInterval;\n\n case ThrottleStrategy.FIXED_FPS:\n default:\n // Simple fixed interval throttling\n return elapsed >= this.performance.currentInterval;\n }\n }\n\n /**\n * Mark the current frame as processed and update timing metrics.\n * Should be called after processing a frame that passed the shouldProcessFrame check.\n *\n * @example\n * if (throttler.shouldProcessFrame()) {\n * // Process frame\n * render();\n * throttler.frameProcessed();\n * }\n */\n public frameProcessed(): void {\n const now = performance.now();\n const frameDuration = now - this.lastFrameTime;\n this.lastFrameTime = now;\n\n // Update performance metrics\n if (this.config.enableMonitoring) {\n this.updatePerformanceMetrics(frameDuration);\n }\n }\n\n /**\n * Update performance metrics with the latest frame duration.\n *\n * @param {number} frameDuration - Duration of the last frame in milliseconds\n * @private\n */\n private updatePerformanceMetrics(frameDuration: number): void {\n // Add to the frame times array (keep last 60 frames)\n this.performance.frameTimes.push(frameDuration);\n if (this.performance.frameTimes.length > 60) {\n this.performance.frameTimes.shift();\n }\n\n // Calculate current FPS\n const avgFrameDuration = this.performance.frameTimes.reduce((sum, time) => sum + time, 0) /\n this.performance.frameTimes.length;\n this.performance.currentFps = 1000 / avgFrameDuration;\n\n // Increment frame count\n this.performance.frameCount++;\n }\n\n /**\n * Update adaptive performance settings based on recent metrics.\n * This method adjusts the frame rate based on the device's capabilities.\n *\n * @param {number} now - Current timestamp in milliseconds\n * @private\n */\n private updateAdaptivePerformance(now: number): void {\n // Only adjust every 1 second\n if (now - this.performance.lastAdjustment < 1000 ||\n this.performance.frameTimes.length < 10) {\n return;\n }\n\n // Calculate average FPS\n const avgFps = this.performance.currentFps;\n\n // Adjust based on performance\n let targetFps = this.config.targetFps!;\n\n if (avgFps < this.config.minFps!) {\n // Performance is too low, reduce target FPS\n targetFps = Math.max(this.config.minFps!, targetFps * 0.8);\n } else if (avgFps > this.config.maxFps!) {\n // Performance is very good, increase target FPS up to max\n targetFps = Math.min(this.config.maxFps!, targetFps * 1.2);\n } else if (avgFps > targetFps * 1.2) {\n // We have headroom, gradually increase target FPS\n targetFps = Math.min(this.config.maxFps!, targetFps * 1.1);\n }\n\n // Update the interval\n this.performance.currentInterval = this.calculateInterval(targetFps);\n this.performance.lastAdjustment = now;\n }\n\n /**\n * Set a specific throttling strategy.\n *\n * @param {ThrottleStrategy} strategy - The throttling strategy to use\n *\n * @example\n * // Switch to adaptive strategy based on device capability\n * if (isLowEndDevice) {\n * throttler.setStrategy(ThrottleStrategy.ADAPTIVE);\n * }\n */\n public setStrategy(strategy: ThrottleStrategy): void {\n this.config.strategy = strategy;\n }\n\n /**\n * Set a specific target FPS.\n *\n * @param {number} fps - Target frames per second (must be > 0)\n *\n * @example\n * // Reduce target FPS to save battery\n * if (isBatteryLow) {\n * throttler.setTargetFps(30);\n * } else {\n * throttler.setTargetFps(60);\n * }\n */\n public setTargetFps(fps: number): void {\n this.config.targetFps = Math.max(1, fps);\n\n // Update the interval if using fixed FPS\n if (this.config.strategy === ThrottleStrategy.FIXED_FPS) {\n this.performance.currentInterval = this.calculateInterval(this.config.targetFps);\n }\n }\n\n /**\n * Get current performance metrics for monitoring and debugging.\n *\n * @returns {Object} Performance information including current FPS, interval, frame count, and strategy\n *\n * @example\n * // Log performance metrics\n * console.log(throttler.getPerformanceMetrics());\n * // Example output: { currentFps: 58.2, targetInterval: 16.67, frameCount: 1242, strategy: 'fixed_fps' }\n */\n public getPerformanceMetrics(): {\n currentFps: number;\n targetInterval: number;\n frameCount: number;\n strategy: ThrottleStrategy;\n } {\n return {\n currentFps: this.performance.currentFps,\n targetInterval: this.performance.currentInterval,\n frameCount: this.performance.frameCount,\n strategy: this.config.strategy!\n };\n }\n}"],"names":["ThrottleStrategy"],"mappings":"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"}