Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upTransfer is seriously strangled while browser tab is in background #1568
Comments
This comment has been minimized.
This comment has been minimized.
|
What would be a better alternative to process.nextTick? It might be possible to detect the browser environment and reassign it to something better or do a PR against browserify. |
This comment has been minimized.
This comment has been minimized.
If possible don't use nextTick at all in both To me it looks like:
now you waisted 8ms or more. Both storage layer don't use the same eventLoop when nextTicket is called in both of them it's more like a chain reaction then a parallel execution It seems to me that this is also almost all pointless b/c of Lines 46 to 47 in 5b7c5ee IndexedDB chunk stores will be wrapped in immediate-chunk-store so when you create a Buffer or Blob it will exit the current eventLoop and exit the current transaction? I don't get what the reason is for using nextTick at all in the stores. Can someone explain what that would be good for? |
This comment has been minimized.
This comment has been minimized.
|
As I understand the use of Maybe browserify should use this setImmediate polyfill instead of |
This comment has been minimized.
This comment has been minimized.
|
The code would need to be changed in the module that Browserify uses for I think that |
This comment has been minimized.
This comment has been minimized.
I kinda know that already and i know what process.nextTick is suppose to solve, but i wonder is it really needed in the stores? I saw that Browserified version earlier - should have linked to it earlier found some solutions here also: https://codepen.io/rafaelcastrocouto/pen/gDFxt seems like mutation observer is the fastest |
This comment has been minimized.
This comment has been minimized.
|
actually setTimeout(fn, 0) is clamped to 4ms but delayed even further when tab is hidden |
This comment has been minimized.
This comment has been minimized.
|
I think this is more of an issue for Browserify to update their |
This comment has been minimized.
This comment has been minimized.
|
so the default process.nextTick does indeed use setTimeout, but only in situation of process.nextTick being called the first time, for recursive calls to process.nextTick it'll be called as soon as the process.nextTick queue is empty. You'll note that we had discussed using things besides setTimeout, but the reason it was vetod for 2 reasons, the first is because the process module gets included in a LOT of code so any bloat on our end would be passed into a staggering number of down stream codebases which is something we wanted to avoid. The second and more subtle reason is that this code get's run in a dizzying array of environments (and if you don't believe me look at the issues related to caching setTimeout) so we would have to deal with a lot of very strange corner cases that could break code even for some users that don't even use process.nextTick. That being said you could always check out my library immediate which is literally just process.nextTick but also using mutation observers and message channels and whatnot it's probably exactly what you want if the default one is not quite doing it for you. |
This comment has been minimized.
This comment has been minimized.
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Building tools such as Webpack, automatically inject process.nextTick which uses https://github.com/defunctzombie/node-process/blob/master/browser.js, which relies on timers. Because it uses timers, things become very slow when the tab is not focused/visible because browsers throttle timers (1Hz), see https://developers.google.com/web/updates/2017/03/background_tabs. The setImmediate polyfill uses a postMessage trick to make it work reliable, even if the tab is not focused. Related: webtorrent/webtorrent#1568
This comment has been minimized.
This comment has been minimized.
|
We need @jimmywarting What do you think about swapping all uses of |
This comment has been minimized.
This comment has been minimized.
Isaac has a point that a callback should always be either async or sync for consistent behavior. but i would not follow he's rule so strictly, if you don't need it to be consistent and you can handle both scenarios then why bother using next tick or immediate at all? In my fork i just removed it, seems to work just fine. I would follow that rule more strictly if it is a one time thing but if it is something that is repeatable and slows down performance under lots of load then i would thing twice before using it. especially when it will be executed in the background. One reason for not using a next cycle would be b/c of the indexed-db layer. |
This comment has been minimized.
This comment has been minimized.
It's about making the API work correctly even when the user of it doesn't code defensively. It prevents really nasty tricky bugs when the user assumes that the function will always be called asynchronously. |
This comment has been minimized.
This comment has been minimized.
|
I assume this issue title was meant to say "background" not "foreground", right? I updated the title. |
This comment has been minimized.
This comment has been minimized.
|
The solution that I'd like to propose here is to switch all I published a package to make it easier to use: https://github.com/feross/queue-microtask |
This comment has been minimized.
This comment has been minimized.
|
If folks would like to start sending PRs to replace usage of |
This comment has been minimized.
This comment has been minimized.
|
Here's a PR for immediate-chunk-store feross/immediate-chunk-store#9 (merged) BTW, this problem goes away when async functions are used instead of callbacks |
This comment has been minimized.
This comment has been minimized.
|
@KayleePop Thanks for the PR :)
Yep. I'd love to switch to a promise-based API at some point :) |
What operating system and Node.js version?
Dosen't affect Node
What version of WebTorrent?
0.103.x
What browser and version? (if using WebTorrent in the browser)
Chrome v72
What did you expect to happen?
Expected
process.nextTickto not usesetTimeoutWhat actually happened?
The problem is with
processbrowserified version ofprocess.nextTickit uses asetTimeout(fn, 0)as a fallback. ThesetTimeoutis delayed well enough in foreground to strangle the speed from 6-7000 kb/s down to just 400 kb/s when one tab is hidden "to save resources". if you instead use two windows the speed will be fast (normal) again.Downloading from hybrid torrents works fine cuz they uses node nextTick version.
So to test this you basically need to upload some large files to instant.io and open up the sharable instant.io link in a new tab or new window
This affect users who want to download something and watch cat videos while its uploading/downloading