New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offline downloads are slow #4166
Comments
We request individual segments, but in some cases, those segments are byte ranges from the same file. We don't have a special case for that, and still download segments one at a time. Options you could explore:
|
Add the possibility to configure the number of downloads in parallel per stream. If you put a higher value the download time can decrease. Related to #4166 Co-authored-by: Joey Parrish <joeyparrish@users.noreply.github.com>
I built an automated test that stores a 4k VP9 version of Sintel, 10 times over to get an average. With the latest code in main (including Alvaro's round-robin 5-parallel download improvement), I get: mean storage time: 75.352 seconds Fetching the same file via wget, I get a transfer rate of 373 Mbit/s. Now I'm going to see if there are any cheap modifications to the system I can make to speed that up. I'm going to try to avoid fully reverting @theodab's changes to prepare for background fetch. |
Commenting out the call to |
Without touching the database, I get: mean storage time: 26.3522 seconds This is a 2.86x improvement in throughput. So I'm going to try to offload the database work as much as possible, and avoid queuing it with the downloads. |
Moving database operations to a separate queue (without collapsing them) doesn't help at all:
|
I also tried decoupling manifest updates from segments and batching manifest updates together, but I never quite got it right. My implementation resulted in inconsistent test failures. The results for that in the table below are just estimates based on what little data I did get. I then tried deferring all manifest updates until the end (but writing individual segments right away). I think this might be the winner. Results below:
At least for my internet connection, this is 187% of the baseline throughput after @avelad's recent change, and 65% of the full throughput we would achieve if never wrote anything to the database. And I think writing segments to the database is a hard requirement for offline playback. 😁 |
I'm blown away by this. For me, the nightly demo site is already ~2x faster than the 3.3.4 demo site (~15s vs ~33s, or 49 Mbit/s vs 22 Mbit/s, for the same Sintel download). I'm excited to see the further improvements. Thanks for tackling this so quickly, too. I can understand that downloads may not be the most popular feature so I wasn't expecting to see much movement on this. |
Thanks belong to @avelad! He not only put together the PR for the first improvement, but quickly followed up by finding the root cause. I would not have been able to put together my tests or my PR without that help. |
By waiting for all segment data to be written to the database before updating the manifest, we can speed up offline storage in the foreground by ~87%. Closes #4166
If a storage operation is aborted (via API, not via closing the page), this will now be cleaned up from the database. More work is needed to find and remove orphaned segments in the database. Related to shaka-project#4166 and follow-up to PR shaka-project#4176.
By waiting for all segment data to be written to the database before updating the manifest, we can speed up offline storage in the foreground by ~87%. Closes #4166
Have you read the FAQ and checked for duplicate open issues?
Yes
What version of Shaka Player are you using?
3.3.2
Can you reproduce the issue with our latest release version?
Yes, on the 3.3.4 demo site
Can you reproduce the issue with the latest code from
main
?Yes, on the nightly demo site
Are you using the demo app or your own custom app?
Custom
If custom app, can you reproduce the issue using our demo app?
Yes
What browser and OS are you using?
Chrome 100/Windows 10
For embedded devices (smart TVs, etc.), what model and firmware version are you using?
What are the manifest and license server URIs?
On the demo app, I've been using the Sintel content on the main page.
https://storage.googleapis.com/shaka-demo-assets/sintel-widevine/dash.mpd
What configuration are you using? What is the output of
player.getConfiguration()
?Config object
From your demo site's
storage.getConfiguration()
, right before theawait storage.store(...)
:What did you do?
On the Shaka demo site, I opened the Chrome dev tools, cleared the network tab, and clicked the download button for Sintel.
What did you expect to happen?
I expected the transfer to download fairly quickly, ideally using all the available bandwidth. For reference, using
wget
, I can download a webm track from Sintel at around 27.25MB/s (or 218 Mbit/s, which is about the limit of my connection).What actually happened?
Once the download via Shaka completed, I took the MB transferred from the Chrome dev tools network page (91.6MB), divided by the last request's start time (33.39 seconds for me), and got 2.74 MB/s (or 21.95Mbit/s) to get a rough estimate. (I also verified that the MPD request was queued at 0ms so I could in theory trust the dev tool timings.) In our custom app, we do calculate an estimated download speed, which is in the same ballpark as Sintel, but for our own content/CDN.
Since Shaka is downloading each byte range as a separate request, I don't expect it to be able to match the throughput of
wget
, but I wasn't expecting it to be ~10x slower.We've also tested our own content being served from the same network (1Gb/s theoretical speeds), and we're still only downloading at around 13MB/s (or 104Mbit/s), so again about 10x below theoretical maxes.
It looks like Shaka is downloading each byte range serially, with the only parallelism being the unique files it's downloading (each audio track and video track will happen in parallel). Eventually though, the download will have completed all the audio tracks and low bitrate video tracks leaving one file still downloading, and it'll only be requesting one byte range at a time. Since there's no ability to pause or resume a download in Shaka, this is pretty inconvenient when downloading a large video, such as a movie.
Also, for more context, I went to YouTube and downloaded a video in the web app with YouTube Premium, which seemed to download at around 9MB/s (or 73Mbit/s). Their downloads are serially transferred as well, yet several times faster. YouTube may have larger segments to reduce each request's overhead. I also realize that YouTube is likely not using Shaka Player at all, so it's comparing apples to oranges.
Is this the expected behavior? Is there a bug preventing faster downloads? Would it even be possible to download multiple byte ranges in parallel for the same track/file?
The text was updated successfully, but these errors were encountered: