Skip to content

Commit

Permalink
improve idle message loop (#2385)
Browse files Browse the repository at this point in the history
总体思路是放宽idle message的调用门槛,让worker message分散到更长的时间周期里返回给主线程,同时不会因为主线程忙而长时间堵塞worker消息的返回。

主要改进如下:
* 改为按百分比设置worker向主线程返回的消息数量,解决繁忙时,worker中消息排队过久的问题
* busyLoop(animFrameLoop)返回更少消息:目前固定为idleLoop中返回比例的一半
* 实测发现workerPool.commit()对性能影响很小,broadcastIdleMessage改为每次loop都会执行。
  • Loading branch information
fuzhenn authored Jul 18, 2024
1 parent d2707dd commit 19df737
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 38 deletions.
9 changes: 2 additions & 7 deletions src/GlobalConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,14 @@ const GlobalConfig = {
//test env
isTest: false,

idleEnable: true,
//idle logging
idleLog: false,
//idle 时间阈值
idleTimeRemaining: 4,
//idle 申请不到idle时,强制执行时间阈值
idleForceTimeThreshold: 100,
//idle 超时阈值
idleTimeout: 1000,
idleForceTimeThreshold: 48,
//worker 数量
workerCount: (getGlobalThis().MAPTALKS_WORKER_COUNT) as number || 0,
//每个Worker Message中封装的task message数量
taskCountPerWorkerMessage: 5,
messagePostRatioPerWorker: 0.3,
//当前运行环境的最大FPS,用户可以手动配置,否则将自动检测并赋值,为地图锁帧渲染准备
maxFPS: 0
};
Expand Down
30 changes: 8 additions & 22 deletions src/core/MicroTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,34 +88,20 @@ function executeMicroTasks() {
}
}

let broadcastIdleMessage = true;
function loop() {
if (broadcastIdleMessage) {
getGlobalWorkerPool().broadcastIdleMessage();
} else {
getGlobalWorkerPool().commit();
}
function loop(isBusy?: boolean) {
const messageRatio = GlobalConfig.messagePostRatioPerWorker * (isBusy ? 0.5 : 1);
getGlobalWorkerPool().commit();
getGlobalWorkerPool().broadcastIdleMessage(messageRatio);
executeMicroTasks();
broadcastIdleMessage = !broadcastIdleMessage;
loopHooks.forEach(func => {
func();
});
}

let idleCallTime = now();
function idleFrameLoop(deadline) {
const { idleTimeRemaining, idleLog } = GlobalConfig;
if (deadline && deadline.timeRemaining) {
const t = deadline.timeRemaining();
if (t >= idleTimeRemaining) {
loop();
idleCallTime = now();
} else {
if (t < idleTimeRemaining && idleLog) {
console.warn('currrent page is busy,the timeRemaining is', t);
}
}
}
function idleFrameLoop() {
loop();
idleCallTime = now();
requestIdleCallback(idleFrameLoop);
}

Expand All @@ -124,7 +110,7 @@ function animFrameLoop() {
const { idleForceTimeThreshold, idleLog } = GlobalConfig;
const time = now();
if (time - idleCallTime > idleForceTimeThreshold) {
loop();
loop(true);
idleCallTime = now();
if (idleLog) {
console.warn(`did not apply for availability, forced run idle`);
Expand Down
15 changes: 8 additions & 7 deletions src/core/worker/Worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const header = `
func(workerExports,self);
adapters[key]=workerExports;
workerExports.initialize && workerExports.initialize(self);
}
onmessage = function (msg) {
msg = msg.data;
Expand All @@ -65,8 +65,8 @@ const header = `
}
// postMessage when main thread idle
if(msg.messageType==='idle'){
var messageCount = msg.messageCount||5;
handleMessageQueue(messageCount);
var messageRatio = msg.messageRatio;
handleMessageQueue(messageRatio);
return;
}
if (msg.messageType === 'batch') {
Expand Down Expand Up @@ -98,16 +98,17 @@ const header = `
}
var messageResultQueue = [];
function handleMessageQueue(messageCount){
function handleMessageQueue(messageRatio){
if(messageResultQueue.length===0){
return;
}
var queues = messageResultQueue.slice(0,messageCount);
var count = Math.ceil((messageRatio || 1) * messageResultQueue.length);
var queues = messageResultQueue.slice(0, count);
queues.forEach(function(queue){
post(queue.callback,queue.err,queue.data,queue.buffers);
});
messageResultQueue=messageResultQueue.slice(messageCount,Infinity);
messageResultQueue=messageResultQueue.slice(count, Infinity);
}
function post(callback, err, data, buffers) {
Expand Down
4 changes: 2 additions & 2 deletions src/core/worker/WorkerPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ export default class WorkerPool {
return this.workers || [];
}

broadcastIdleMessage() {
broadcastIdleMessage(messageRatio: number) {
const workers = this.getWorkers();
workers.forEach(worker => {
worker.postMessage({ messageType: 'idle', messageCount: GlobalConfig.taskCountPerWorkerMessage });
worker.postMessage({ messageType: 'idle', messageRatio });
});
return this;
}
Expand Down

0 comments on commit 19df737

Please sign in to comment.