Merge pull request #640 from getmaxun/browser-perf

feat: browser performance optimization
This commit is contained in:
Karishma Shukla
2025-06-12 21:26:42 +05:30
committed by GitHub
4 changed files with 219 additions and 154 deletions

View File

@@ -25,6 +25,13 @@ const MEMORY_CONFIG = {
heapUsageThreshold: 0.7 // 70% (reduced threshold to react earlier)
};
const DEFAULT_VIEWPORT = {
width: 1280,
height: 720,
deviceScaleFactor: 1,
mobile: false
};
const SCREENCAST_CONFIG: {
format: "jpeg" | "png";
maxWidth: number;
@@ -32,13 +39,17 @@ const SCREENCAST_CONFIG: {
targetFPS: number;
compressionQuality: number;
maxQueueSize: number;
skipFrameThreshold: number,
enableAdaptiveQuality: boolean,
} = {
format: 'png',
maxWidth: 1280,
maxHeight: 720,
targetFPS: 15,
compressionQuality: 0.95,
maxQueueSize: 1
format: 'jpeg',
maxWidth: DEFAULT_VIEWPORT.width,
maxHeight: DEFAULT_VIEWPORT.height,
targetFPS: 30,
compressionQuality: 0.8,
maxQueueSize: 2,
skipFrameThreshold: 100,
enableAdaptiveQuality: true,
};
/**
@@ -125,6 +136,18 @@ export class RemoteBrowser {
this.generator = new WorkflowGenerator(socket, poolId);
}
private cleanupMemory(): void {
if (this.screenshotQueue.length > 10) {
this.screenshotQueue = this.screenshotQueue.slice(-3); // Keep only last 3
}
}
private setupMemoryCleanup(): void {
setInterval(() => {
this.cleanupMemory();
}, 30000); // Every 30 seconds
}
private initializeMemoryManagement(): void {
setInterval(() => {
const memoryUsage = process.memoryUsage();
@@ -412,6 +435,7 @@ export class RemoteBrowser {
}
}
this.setupMemoryCleanup();
// this.initializeMemoryManagement();
};
@@ -1399,7 +1423,7 @@ export class RemoteBrowser {
*/
private emitScreenshot = async (payload: Buffer, viewportSize?: { width: number, height: number }): Promise<void> => {
if (this.screenshotQueue.length > SCREENCAST_CONFIG.maxQueueSize) {
this.screenshotQueue = this.screenshotQueue.slice(-SCREENCAST_CONFIG.maxQueueSize);
this.screenshotQueue = this.screenshotQueue.slice(-1);
}
if (this.isProcessingScreenshot) {
@@ -1414,7 +1438,7 @@ export class RemoteBrowser {
try {
const optimizationPromise = this.optimizeScreenshot(payload);
const timeoutPromise = new Promise<Buffer>((resolve) => {
setTimeout(() => resolve(payload), 150);
setTimeout(() => resolve(payload), 100);
});
const optimizedScreenshot = await Promise.race([optimizationPromise, timeoutPromise]);
@@ -1423,10 +1447,12 @@ export class RemoteBrowser {
payload = null as any;
this.socket.emit('screencast', {
setImmediate(async () => {
this.socket.emit('screencast', {
image: dataWithMimeType,
userId: this.userId,
viewport: viewportSize || await this.currentPage?.viewportSize() || null
});
});
} catch (error) {
logger.error('Screenshot emission failed:', error);
@@ -1434,24 +1460,27 @@ export class RemoteBrowser {
const base64Data = payload.toString('base64');
const dataWithMimeType = `data:image/png;base64,${base64Data}`;
this.socket.emit('screencast', {
image: dataWithMimeType,
userId: this.userId,
viewport: viewportSize || await this.currentPage?.viewportSize() || null
setImmediate(async () => {
this.socket.emit('screencast', {
image: dataWithMimeType,
userId: this.userId,
viewport: viewportSize || await this.currentPage?.viewportSize() || null
});
});
} catch (e) {
logger.error('Fallback screenshot emission also failed:', e);
}
} finally {
this.isProcessingScreenshot = false;
if (this.screenshotQueue.length > 0) {
const nextScreenshot = this.screenshotQueue.shift();
if (nextScreenshot) {
setTimeout(() => {
this.emitScreenshot(nextScreenshot);
}, 1000 / SCREENCAST_CONFIG.targetFPS);
}
const nextScreenshot = this.screenshotQueue.shift();
if (nextScreenshot) {
const delay = this.screenshotQueue.length > 0 ? 16 : 33;
setTimeout(() => {
this.emitScreenshot(nextScreenshot);
}, delay);
}
}
}
};