Debounce cuncurrency performance fix
When MutationObserver or IntersectionObserver triggers the same function multiple times, the current debounce implementation limits new identical function starts to the minimum wait time.
However, if the debounced function is asynchronous and takes longer to complete than the defined wait time, multiple instances of the same function can still start. This leads to concurrent executions that may “untranslate” the same content simultaneously and issue duplicate network requests (when caching was not done in time, as the network response was not returned within the previous wait time).
The issue causes wastage of CPU/GPU cycles as more redundant instances are started. The issue is worse on slow processors, where the execution time of all functions is naturally longer, but, as the minimum wait time is the same, the debounce will start more and more instances of the same functions all running simultaneously (and new starts will potentially make the first call, which should be closer to completion, slower).
Similarly, the issue is also worsened by slow internet. When the internet is slow, network responses take naturally longer, but, as the minimum wait time is the same, more and more duplicate network requests will be raised while the first did not respond just yet (before the caching of the first response can take effect).
This update modifies the debounce behaviour to track the state of the last promise and only allow a new identical function to start after the previous one finishes.
As a safety measure, a new maxLongRunningMs argument has been added (default: waitMinMs * 10). If a pending promise exceeds this duration, its “running” status will be ignored, allowing a new queued call to proceed.
NOTE that each function signature retains a separate wait and queue. So while function A is pending with another A in the queue, function B can still start at any time, running on a separate thread.
### Key Changes
- Added activePromise tracking per function signature.
- Ensured new async calls only start after previous completion.
- Introduced maxLongRunningMs (default = waitMinMs * 10) as a timeout safeguard.
- Maintained backward compatibility for synchronous functions.
- Added more tests to `debounce.test.js` to verify behaviour
合并状态:未合并 3 条评论