-
-
Notifications
You must be signed in to change notification settings - Fork 828
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
Async / Chunked Preloading #4925
Conversation
Thank you! Future thoughts: I'm not 100% convinced I want to use Rust async/await all the way through the stack -- my first attempt would be to wrap
Part 1 definitely benefits from using async/await. Parts 2 and 3, I'm not completely sure. Part 3 is CPU bound, so a long running tessellation will block everything on both web and the current desktop executor. We eventually want to toss Part 3 to different threads when possible (particularly on desktop). On destkop, we can switch to a thread pool executor. On web, perhaps someday we toss the tessellation to a worker, but I'm not sure this will mesh cleanly with Rust async (for one, the worker code has to be in a separate JS file). All that said, I'm not against relying on async, but just weighing the pros/cons -- I'd like to see the benefits of going one way over the other. Another note: |
My original thought was to make the platform specific code handle scheduling the preload directly, by changing, say, Furthermore, we already do need an asynchronous process for preloading, because user-initiated movie loads exist and need to be able to send I feel like I should probably rename Moving to a proper executor on desktop probably would help; I wrote the existing ones (the null executor and desktop's GLUTIN-based executor) as a bare-minimum effort to get some asynchronous behavior working. One other thing I'd like to do is make some macros or something to make async code less painful to write with our context system, though I'm not sure exactly how to do that yet. |
That still doesn't mean it needs the async/await machinery, right? I'm not saying it's objectively worse - it definitely makes it simpler to manage state than if partial preload was manually interspersed with |
@kmeisthax, will the task above solve #1561 (comment)? Many thanks for your help. |
@ousia No, as your problem appears to have to do with the way AVM1 handles display object name resolution. I've posted a question in that other issue and I may be able to fix it quickly if I'm right about the root cause. It will be a different PR. |
@kmeisthax, many thanks for your reply and your help. It would be great to have #1561 fixed. |
So, one thing I noticed early on is that [S] Cascade (the first movie I tried) doesn't preload properly. It does remain mostly interactive on desktop, at least. This appears to be a development oversight on the part of the original creator; all of the assets are on frame 1 before the preloader. This isn't a problem on Flash Player because it doesn't take nearly as long to scan through SWF data as we do in the Other preloaders appear to be working. I don't think this PR is just a draft anymore... I'm going to say that this patch is going to need extra QA before it merges, because it affects fundamental parts of the player. I'd specifically like to see which preloaders do and don't load correctly with this. There's probably other movies that have very heavy assets in frame 1, and will probably not preload correctly; but I'd like to know if there's any other problems. OTOH, any movie that skips it's preloader on this patch only would be a huge red flag that I missed some other API surface for getting loader progress. I'd also like to know what people's feelings would be about me renaming @adrian17 AVM1 has (I should point out that everything I wrote about adding a new Part of the reason why it's difficult to understand what's going on in |
8824c34
to
ce41664
Compare
This technically works, but if multiple preload chunks are ran at once, tests start failing and Bad Things happen.
Right now, synchronous preload contexts do not set a chunk limit, while asynchronous ones have a chunk size of one.
… other tasks without a particular event source.
This massively improves the responsiveness of Ruffle when async preloading occurs.
…ground task suspension
…efore it can be called
The preload frame counting logic starts from one and continues to the end of the file, which results in a completely preloaded movie having one more frame "loaded" than there is in the file. This fixes that.
If we don't preload every movie clip we make, then they'll indicate themselves as not having been fully loaded yet, even though they are.
…efore running frames.
An "empty clip" is any clip created by the `new` or `new_with_avm2` function, intended for dynamically-created movie clips with no association to a movie symbol.
This requires estimating a count of bytes loaded of the original compressed stream, even though we only have uncompressed byte totals at this point. I instead rescale the uncompressed bytes by the compressed count to roughly estimate what would be the `bytesLoaded` had we been actually streaming bytes in and preloading them synchronously.
…nd runtime. Actions are abstract; here we're using it to count bytes loaded (as a proxy for execution time). AVM code could potentially be adapted to count operations run instead.
…hecked after every 10000 bytes.
…rent movie's frame time.
ce41664
to
d10421c
Compare
Note that this is a serious usability issue for some of the heavier content, as it can otherwise take a few minutes to load. On the web, users are known to abandon pages after just a few seconds... |
FWIW I tried implementing this without the So, the reason why I used async is because child movie loads need to still fire completion events in AVM1 (and AVM2 when we implement loading there). Yes, the root movie technically doesn't need that, and we can just make movie clips to remember to fire their own completion events instead of letting an async task do that. The problem with this asyncless approach is that the proposed alternative, For the record, that means:
So, why isn't this a problem with We can't make all clients call That being said, one thing I am going to do is have |
I tried using this PR in my private personal multifile flash project. The issue I faced was that loading stops midway, with only half the game's files loaded. This issue doesn't appear with the master build, it only appears when using this PR. I have privately sent the link to my project to kmeisthax. |
Have you made any progress on fixing the issues? This PR has been open for a while now... |
So, I guess this can be closed now? |
finally |
It seems that this and/or other improvements have cut down the Banned from Equestria 1.5 load time from 70 seconds to 33 seconds (on my machine), which is of course a large and welcome improvement, but that content is supposed to load instantly. |
This is being closed due to being superseded by #7858 ;) But hopefully that one is much closer to being complete.
This change wasn't merged yet. |
Right, of course, I was careless. It seems that there has been large related improvements since Ruffle nightly 2022-06-25, then...
Right, of course what really matters here is the user-perceived loading time...
🎉🎉🎉 GOD, then I can't wait to upgrade to this once it lands, then!!! 🎉🎉🎉 |
On my i9 11900 load time 8 sec for this game |
Yes, I realize everything loads quickly on extremely powerful computers. By the way, this used to take around 3:30 to load on my slow computer. |
This PR implements an asynchronous version of the preload step of Ruffle's movie clip lifecycle. This allows very complicated SWFs to load, remain interactive, and not bottleneck the player as they are loading.
DefineSprite
tagspreload
step status to movie preloaders