Heya!

I wanted to check the web loading times and sizes for Godot compared to Unity. I have a long running test scene for Unity that compares different versions with different settings (link) and started replicating this for Godot (link).
First I want to get a nice basis before I start comparing different Godot versions. The two things I noticed now are:

  1. File sizes are a lot bigger compared to Unity (where I can get away with 2.5MB for the whole project)
  2. The loading time to start the engine in the browser takes quite long

File size

With Unity you have the option to select a compression for the files (gzip or brotli). I really like this setting, since I don't have to do anything afterwards to compress them and the server also does not have to compress them on the fly every time it serves the file (especially for brotli with high compression this would be quite some overhead).
I found the documentation for custom html templates and there is the option to hand over the filePath for the wasm to the init method. I would like to do something along the lines of

const myWasm = 'mygame.wasm.gz';
const myPck = 'mygame.pck.gz';
const engine = new Engine();
Promise.all([
    // Load and init the engine
    engine.init(myWasm),
    // And the pck concurrently
    engine.preloadFile(myPck),
]).then(() => {
    // Now start the engine.
    return engine.start({ args: ['--main-pack', myPck] });
}).then(() => {
    console.log('Engine has started!');
});

But sadly this throws away my .gz ending. I saw some others adding pako to unpack data, but I feel like this should be easier to achieve.Do you have any tips on how I can get a compressed version without adding an extra unpacker?

Loading times

Do you have any tips on how I can improve those, or is this in general an issue for Godot web projects?

    11 days later

    Has no one ventured into having pre-built gzip/brotli files that are loaded correctly through the server configuration?

    I open sourced my current state with a custom html template: https://github.com/JohannesDeml/Godot-WebGL-LoadingTest
    I think the next thing for me will be building godot with less features and then having a look at loading times (since I'm a bit underwhelmed at the moment).

    Those 3 MB Unity builds are impressively small.

    Johannski I'd also love to know if someone managed to compress/decompress a Godot web build easily. I will say that I managed to reduce my web file size by optimizing the wasm file with binaryen. Here's an excerpt of my old post:

    Not sure if this is well known or not, but I found this very useful before publishing my web builds. My game.wasm file went from 27.34mb --> 23.49mb. The gains are lower after compressing the web build to a zip file (6.9mb --> 6.2mb), but it's still pretty good considering how big Godot 4's web builds are. This shouldn't affect performance at all since it's just optimizing the wasm file.

    1. Download Binaryen

    2. Extract it somewhere and go open the bin folder

    3. Add this folder to your path so it's easy to reach OR copy the .wasm file from your export into the bin folder (then move it back after optimizing)

    4. Open the terminal and run this command: wasm-opt game.wasm -o game_out.wasm --enable-bulk-memory --enable-threads --enable-simd -O --intrinsic-lowering -O . Replace game.wasm with the file's name.

    5. Wait a while, this may take a few minutes. Don't close the terminal.

    6. It should output the optimized file! Delete the old one and rename the new one to have the same name. Move the new .wasm back to your export folder if you're not already there and you're done.

    Note that this is for Godot 4.

    I also want to point out that web builds are drastically smaller in Godot 3. The old version of Godot also doesn't require SharedArrayBuffers to run, so it may be preferable if you're specifically targetting the web.

      popcar2
      Ah very interesting, I didn't know there was a tool to optimize an already created wasm file. Sadly I had no luck with binaryen 116 and godot 4.1.2 build (neither with or without Export with debug). I'm getting a lot of validation errors, the start of the output looks like this:

      Click to reveal Click to hide
      C:\Data\Documents\Godot\Own\Godot-WebGL-LoadingTest\Builds\WebGL\4.1.2>wasm-opt Godot-WebGL-LoadingTest.wasm -o Godot-WebGL-LoadingTest_out.wasm --enable-bulk-memory --enable-threads --enable-simd -O --intrinsic-lowering -O
      [wasm-validator error in function 1134] unexpected false: all used features should be allowed, on
      (i32.extend8_s
       (local.get $2)
      )
      [wasm-validator error in function 1920] unexpected false: all used features should be allowed, on
      (i32.extend16_s
       (local.get $5)
      )
      [wasm-validator error in function 1930] unexpected false: all used features should be allowed, on
      (i32.extend16_s
       (i32.add
        (i32.mul
         (local.get $4)
         (i32.const 61936)
        )
        (local.get $3)
       )
      )
      [wasm-validator error in function 1930] unexpected false: all used features should be allowed, on
      (i32.extend16_s
       (i32.div_s
        (i32.extend16_s
         (i32.add
          (i32.mul
           (local.get $4)
           (i32.const 61936)
          )
          (local.get $3)
         )
        )
        (i32.const 60)
       )
      )
      ```!<

      Did you encounter this as well? Or could you meybe check if it works for you and I just have problems with my setup? (Build is attached in the release).

      @Toxe Yeah, that's why I was quite surprised of how big the builds are for godot. But on the other hand, Unity is also stripping all code it can when exporting the project making it waaaay slower to export. I was expecting to see something similar for godot, but if I got this right, this is kind of a manual step with a custom export template.

        Johannski I was expecting to see something similar for godot, but if I got this right, this is kind of a manual step with a custom export template.

        Godot export templates are prebuilt and there is no compilation happening during export AFAIK. So as you said, that'd be a manual step. OTOH, once you've compiled a stripped down godot and export template that fits your needs, so long as it fits following projects too, you can reuse it so project 'exporting' will continue to be fast I guess.

          popcar2
          Awesome, thanks for taking the time to run it. I will test if i can get it running on Ubuntu, when I have time to boot it up again. Good to know that it seems to be about my setup and that it still should work in general!

          Megalomaniak
          Yep, that's what I understood as well. I like that this only needs to be done once (per godot version), but it is a bit inconvenient to set everything up to build godot from source to get the template (at least when you're used to Unity). On the other hand, I wanted to have a look if I can contribute to godot anyways, so getting the environment ready is not that bad after all 😉

          9 days later

          Okay, I now finally got the custom template to build (had to fight a lot with different emscripten versions) - finally got it working with emscripten 3.1.41 with the additional link flags -Wl,-u,htonl and a hack to hardcode the version. I generated the custom-py file with https://godot-build-options-generator.github.io and tried to disable everything that I don't need. The resulting template wasm file is 25.17 MB, the full exported project is 4.1.2-custom-template (25.04 MB) - this is a size improvement of a bit more than 2MB compared to the normal build, but is 2MB larger than the wasm-optoptimization suggested by @popcar2. I was expecting a lot better results since I tried to disable as much as possible from the modules I don't use. Is there anything else I can do other than trying to run wasm-opt on the new build? Are there modules missing from the tool I found that still could be stripped? Or did I already hit the minimum size you can reach with Godot 4 for the web?

          The 25 MB of course sound a lot worse than they actually are, since they are not yet compressed. If I go with brotli compression I can get the whole build down to 4MB. however, this would bring me back to my initial question on how to load this pre-compressed file similar to what Unity does. If anyone has input on that I would love to hear it!

          a year later

          Heya!

          I finally found some time to create a proper CI setup, which should help me iterate faster. The CI script does the following:

          • Create the godot build
          • run wasm-opt on the created wasm
          • brotli and gzip compress all .js and .wasm files
          • Deploy the result to my server
            Additionally, I got my server configured correctly to load the brotli compressed version, so that is finally a bsis with which I feel like it is fair to compare the builds with Unity's builds. Here is the latest build: 4.3.0-webgl2 (5.33 MB), And a list of all builds: Live Demos
            The 5.33 MB are not entirely correct, the Network tab tells me I need 5.61MB, I will need to look into my calculations there, but it is roughly correct

          One thing that confuses me quite a bit is the wasm-opt has almost no impact at all. I forked an action to be able to use the latest binaryen version and added logging to see how much impact the compression had (binaryen-wasm-opt github action). There I also added a test to compress a godot wasm (code). I took the parameters from @popcar2 , but I don't see a relevant change in the logs:

          Input file size: 35376909 bytes
          Writing optimized wasm file to '/github/workspace/godot-4.3_optimized.wasm'
          Executing 'wasm-opt /github/workspace/tests/godot-4.3.wasm -o /github/workspace/godot-4.3_optimized.wasm --enable-bulk-memory --enable-threads --enable-exception-handling --enable-simd -O --intrinsic-lowering -O'
          Output file size: 35348406 bytes (0% reduction)

          Any ideas why this is the case?

            7 days later

            Johannski

            I just had a check with the old file I provided that @popcar2 back then compressed and here is the output:

             Got arguments: [Some("tests/godot-4.1.2.wasm"), Some("godot-4.1.2_optimized.wasm"), None, Some("--enable-bulk-memory --enable-threads --enable-exception-handling --enable-simd -O --intrinsic-lowering -O"), Some("122")]
            Downloading binaryen from: https://github.com/WebAssembly/binaryen/releases/download/version_122/binaryen-version_122-x86_64-linux.tar.gz
            Searching for file matching '/github/workspace/tests/godot-4.1.2.wasm'
            Optimizing '/github/workspace/tests/godot-4.1.2.wasm'
            Input file size: 27907743 bytes
            Writing optimized wasm file to '/github/workspace/godot-4.1.2_optimized.wasm'
            Executing 'wasm-opt /github/workspace/tests/godot-4.1.2.wasm -o /github/workspace/godot-4.1.2_optimized.wasm --enable-bulk-memory --enable-threads --enable-exception-handling --enable-simd -O --intrinsic-lowering -O'
            Output file size: 23723532 bytes (15% reduction)

            So there we have the nice 15% reduction, not sure why this does not work anymore with Godot 4.3 (is it bigger, but also better optimized already?).

            Anyways, so I guess I will skip the wasm-opt step for now, since it does not really improve anything, but does take some time to finish.

            a month later

            I found the solution in this blog post - The parameters you need to use are -all --post-emscripten -Oz.

            I also moved the thread to here, since I feel like this forum is a bit dead.