godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.46k stars 21.27k forks source link

Godot HTML5 games have a really long time to first interaction #41118

Open Zireael07 opened 4 years ago

Zireael07 commented 4 years ago

Godot version: Varies (see below)

OS/device including version: Computer: Linux Manjaro, Intel HD Kaby Lake (UHD Graphics 620), Brave browser (so Chromium-based) Mobile: LG K61, Chrome both tested on the same, an LTE (!) connection

Issue description: Godot HTML5 games have a very long time to first interaction (what is called TTI in web development jargon) As I couldn't inject any sort of a time() call into already released projects, I used a stopwatch on my mobile to time the computer and a stopwatch website to time the mobile.

1) Tanks of Freedom Computer: ~31 seconds Mobile: 1 min 31 seconds (I counted the time to the start of the in-game splash screen, not to main menu)

2) Faless's textedit demo Computer: ~10 seconds Mobile: ~34 seconds

Steps to reproduce: Follow the links, get a stopwatch ready...

Minimal reproduction project: Faless's textedit demo probably qualifies? Note that it uses GLES2, which is recommended for web/mobile, AND is just two controls slapped on...

cc'ing @Faless

Calinou commented 4 years ago

This is probably due to the large WebAssembly payload. I doubt much can be done about it unless you specifically build an HTML5 export template that disables all the modules you don't need.

Also, make sure to upload your project on a website that supports gzip compression such as GitHub Pages. Most notably, itch.io doesn't support this as they let the engine itself do it (like Unity). However, this approach is less efficient. Unfortunately, there's no way for you to enable it on a per-project basis :slightly_frowning_face:

Give GDScript Online a try. It applies all of the advice outlined above.

Zireael07 commented 4 years ago

The time I counted is both the time it takes for anything vaguely relevant to show up (the loading spinner) and the loading bar/loading text depending on Godot version used. I am not too sure what the difference between the two is (is one the initial payload and the other loading assets/pck?) BTW the spinner is fairly slow to spin on mobile, leading to impression that the page hanged up.

This is probably due to the large WebAssembly payload. I doubt much can be done about it unless you specifically build an HTML5 export template that disables all the modules you don't need.

Would it be possible to get a "2D" switch in the export window, that would disable 3D modules? I suspect this is unnecessarily bloating many 2D projects (which I expect the majority of web exports to be)

A more involved fix would be to move away from Emscripten in favor of e.g. https://github.com/schellingb/ZillaLib (Zlib license ought to be compatible), except we'd need to add fake filesystem support to it (I believe we are not using any more Emscripten features such as threads...?)

Zireael07 commented 4 years ago

Just for reference: GDScript online: 7 seconds on computer, 20 seconds on mobile Looks like gzip compression does indeed shave off a bit.

Calinou commented 4 years ago

Would it be possible to get a "2D" switch in the export window, that would disable 3D modules? I suspect this is unnecessarily bloating many 2D projects (which I expect the majority of web exports to be)

This is feasible, but we'd have to compile 2D-only export templates in addition to the current ones. This would make export template TPZ archives significantly larger (600-700 MB).

Zireael07 commented 4 years ago

What happened to the idea of being able to download only those export templates that you are interested in (e.g. only Windows, only web)?

Calinou commented 4 years ago

@Zireael07 This was requested in https://github.com/godotengine/godot-proposals/issues/647, but keep in mind adding more export templates may require designing a more complex GUI for that feature.

That said, we could display only one button per platform and include both 2D and 2D + 3D export templates in the same TPZ. This is probably fine since most people will only download 3-4 platforms at most.

Zireael07 commented 4 years ago

I expect web is the platform that needs 3D excluded the most, desktop doesn't suffer visibly from the added bloat. And putting both versions in the same tpz would be fine, too.

mindinsomnia commented 4 years ago

Would it be possible for Godot to automatically cull modules during export that aren't used?

Calinou commented 4 years ago

@mindinsomnia That would require a compiler toolchain to be present, in addition to being able to compile for the target platform from the OS the editor is currently running on. Unfortunately, both of these are far to be guaranteed, so I don't think it's an idea worth pursuing.

See also https://github.com/godotengine/godot-proposals/issues/1001.

Zireael07 commented 4 years ago

Most notably, itch.io doesn't support this as they let the engine itself do it (like Unity). However, this approach is less efficient.

Could Godot then handle it somehow? I imagine gzip doesn't do much for pck, which is already zipped, but it could help with the wasm payload...

Calinou commented 4 years ago

I imagine gzip doesn't do much for pck, which is already zipped

gzip or Brotli will help significantly for most PCK files, as a PCK isn't compressed. (PCK files can contain compressed data, but they can and will often contain uncompressed data as well.)

Could Godot then handle it somehow?

This was requested here already: https://github.com/godotengine/godot/issues/20996

Zireael07 commented 4 years ago

One more thing I just realized: most Emscripten projects use a loading bar where Godot has a spinner (because the latter Loading... or loading bar is clearly Godot's)

Examples: https://marukrap.github.io/RoguelikeTutorial2020/Demos/Part10.html https://personal-1094.web.app/gemrb.html (this is Baldur's Gate 2 running in GemRB on Emscripten - I haven't timed the loading but it's fairly fast for such a large game) EDIT: Baldur's Gate 2 TTI is 24s on desktop. So a huge AAA 2d RPG game loads faster than Tanks of Freedom...

A loading bar would make it clearer to the user that the page hasn't hanged...

Calinou commented 4 years ago

@Zireael07 Godot uses both a loading bar and a spinner depending on the loading state. When downloading the PCK, a loading bar is displayed. When initializing the engine, a spinner is displayed.

We can only display a loading bar if we can know the loading percentage.

Zireael07 commented 4 years ago

@Calinou: As the linked sites show, Emscripten projects show a loading bar when initializing the project. (It literally shows 'initializing' in marukrap's demo) It seems to work both for toy demos and for big projects.

Faless commented 4 years ago

I'll chime in with a couple of remarks:

Further improvements might include fixes to properly support streaming instantiation of WASM in browsers that supports it (emscripten do it by default, but our custom code that shows the loading bar overrides it for now).

Zireael07 commented 4 years ago

@Faless: The linked version above takes around 11s from click on the link to splash screen (computer).

Haven't tried mobile yet, but I expect it'll be similar to the results from the text edit demo. 10s on computer and 30s on mobile seem to be the lower bound, and neither looks good for a prospective Godot user who wants to target HTML5 (Tanks of Freedom is a small game, nowhere close to an enormous game like Baldur's Gate 2 in terms of hours of content inside or assets...)

akien-mga commented 4 years ago

Can you try comparing it with this version?. A regular 3.2 WASM build (but with LTO enabled), and served with compression, although my server has a 100 MiB/s connection, so it might be a bottleneck for you).

For me this version loads in ~4 seconds on desktop (Linux, Firefox Nightly) and ~6 seconds on mobile (Android, Firefox Beta) (counting from entering the URL, so includes download time). That's pretty good, most big websites nowadays take the same time to load.

Faless commented 4 years ago

Haven't tried mobile yet, but I expect it'll be similar to the results from the text edit demo. 10s on computer and 30s on mobile seem to be the lower bound,

I'm seeing ~11 sec loading time on my phone (Xiaomi Mi A3, Firefox).

Tanks of Freedom is a small game, nowhere close to an enormous game like Baldur's Gate 2 in terms of hours of content inside or assets...

Yeah, but this has very little to do with initial load times, most of the time is due to WASM loading/instantiation (beside the download of the assets, which is already done in parallel).

Zireael07 commented 4 years ago

Hm, you guys are testing with cache cleared? I do (to make sure we're not seeing fast times due to reusing cache) - if you do too, maybe it's a matter of the browser (Chrome vs Firefox)

Faless commented 4 years ago

Hm, you guys are testing with cache cleared?

Yes, and the cache won't affect timing beside the download time unless you are on a poor connection (12 MiB engine + 12 MiB assets = 24 MiB, but the engine is served compressed < 4 MiB so it's a total of 16 MiB which is ~7 seconds on a poor DSL connection and <2 sec on a regular 100 Mib/s). (I hope I did my maths correctly).

I gave Chrome a try, I get the same result on Linux (actually, slightly better then FF), While on mobile it's a bit slower (~15 secs).

I guess the difference is in phone/PC performances? Anyway, would be nice if you could try that version on mobile too so we have actual data. Can you also provide the specs of your PC? And maybe try with FF or Chrome? (not sure which version of chromium brave uses, and if they have some custom patches that might affect performances).

slabgames commented 3 years ago

Hi, thanks for replacing XHR with Fetch. But it also breaks my code to preload gzipped file using this script https://gist.github.com/natrim/1a19f4b7668e0474897f3f28171f3b33

Is there a way to get this to work with Fetch?

Calinou commented 3 years ago

@slabgames Can't you rely on the web server serving precompressed files instead? This way, you can also use Brotli compression (even if the web server doesn't support it).

Here's an example for Apache: https://gist.github.com/Calinou/fc0fe1003c95380054f0084f9476e476

slabgames commented 3 years ago

@Calinou Thanks for answering. I'm afraid I can't do server side compression, since I'm not going to serve the game on my own server. That's why I try to find a way to do it on client side