Search Unity

Question How can the "linking build.js (wasm)" time be accellerated

Discussion in 'Web' started by manuelgoellnitz, Apr 19, 2023.

  1. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
    In our WebGL project with 2022.1.x the webgl building time was < 15 minutes.
    With 2022.2.x it takes 1 h 20 min. (I tried serveral versions)
    "linking build.js (wasm)" is what takes so long now.

    How can that be reduced?
     
  2. KamilCSPS

    KamilCSPS

    Joined:
    May 21, 2020
    Posts:
    448
    manuelgoellnitz likes this.
  3. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
    Ah thx.

    Switching to "faster build time" as mentioned somewhere in the thread helped.
     
  4. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    1,794
    Mine spent <40s building my project and 17 minutes linking build.js .. part of the reason I would never use unitys we can build it for you system because after all you get some free cpu but it then charges you - for what, for time doing what? how do you link a javascript file? its text.
     
  5. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    Currently if doing a Release build and Code Optimization is set to "Runtime Speed" or "Disk Size", Unity will enable LLVM Link-Time Optimizations (LTO) to get the best optimizations possible.
    upload_2023-8-30_14-17-8.png

    However it turns out that these optimizations are very costly in terms of time. In a future update, we are looking to add a control to configure LTO optimizations separately. (i.e. "Runtime Speed" vs "Runtime Speed with LTO"). That way users can do Runtime Speed or Disk Size optimized builds without enabling the slow LLVM LTO pass.

    Those new LTO-disabled passes will still not be as fast as the "Shorter Build Time" option. That option does not have LTO enabled. So if build speeds are of biggest concern, it is best recommended to enable "Shorter Build Time" option.

    Additionally, in Unity 2023.2 and newer, enabling *both* WebAssembly.Table and BigInt options will also improve build times.
    upload_2023-8-30_14-20-25.png
     
    KamilCSPS likes this.
  6. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    1,794
    @jukka_j out of interest then are you able to explain what "linking build.js" is doing? even at a general wafty level? cos 17 mins to generate a <8mb file for build.wasm.* or the wholel 71k of build.framework.js (as it does mention js as build.js) my whole thing clocks in <12mb including the html/images how is that a 17 minute build?
     
  7. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    "Linking build.js" stage is when the build is out of Unity's hands, and the final Emscripten compiler is run, which, roughly,

    1) runs the Emscripten front-end to find all necessary inputs to the build (.o, .a, .bc), and configures the needed build flags ( https://emscripten.org/ ),
    2) runs LLVM optimization passes on them ( https://llvm.org/docs/Passes.html ),
    3) then runs LTO optimizations on the code ( https://llvm.org/docs/LinkTimeOptimization.html ) ,
    4) then runs LLVM WebAssembly lowering backend on the result to generate the .wasm output ( https://github.com/llvm/llvm-project/tree/main/llvm/lib/Target/WebAssembly#readme ),
    5) then runs the Binaryen optimizer to perform wasm-specific code optimization passes ( https://github.com/WebAssembly/binaryen ),
    6) and the needed WebAssembly backwards compatibility passes ( e.g. https://github.com/WebAssembly/binaryen/blob/main/src/passes/GenerateDynCalls.cpp , and others ),
    7) then Emscripten back-end is run to figure out the needed system libraries to link with (WebAudio, WebGL, input, HTML5 DOM) and other JS libraries to link ( https://github.com/emscripten-core/emscripten/blob/main/tools/system_libs.py ),
    8) and a cross-language linking between JS and Wasm is performed ( ( https://github.com/emscripten-core/emscripten/blob/main/src/jsifier.js )
    9) a metadce optimization pass that performs dead code elimination across JS+Wasm together is run ( https://github.com/emscripten-core/...b91f60c5b6682cb/tools/acorn-optimizer.js#L601 )
    10) and then the final build.js is written by Emscripten, which Unity takes and mixes with the user's WebGL Template to generate the final output files

    If you are seeing a 17 minute long build, it is probably the phase 3) above that has been identified as the slowest part of the build, and like mentioned above, choosing "Shorter Build Time" can help with that.

    If you tick the WebAssembly.Table and BigInt Language Features checkboxes during the build, then stage 6) is avoided.

    I do not have any kind of "megabytes/minute" standard to give on these types of processes of what limit would be reasonable. If you would like to dig in deeper, there exists documentation for a toolchain profiler for Emscripten at https://emscripten.org/docs/optimizing/Profiling-Toolchain.html that can be used to generate a detailed swimlane of the above processes, and figure out how long each of them take.
     
    Greenhapi, FelixK-FG and bugfinders like this.
  8. KamilCSPS

    KamilCSPS

    Joined:
    May 21, 2020
    Posts:
    448
    bugfinders likes this.
  9. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    > We tried to raise the issue in here (...) with @JustBeanUnity but to no avail.

    Oh no, totally the opposite. It was @JustBeanUnity in the first place who internally raised this in the web team, which got the team looking into investigating the change in the LTO build times. So big thanks for doing so.
     
    KamilCSPS likes this.
  10. KamilCSPS

    KamilCSPS

    Joined:
    May 21, 2020
    Posts:
    448
    Good to hear, thank you.

    Do you know if the multithreading aspect (AMD vs Intel, etc.) of this issue has been investigated internally and if there is an issue # we can use to track?
     
  11. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    I believe the multithreading aspect (build config/machine X seems to run singlethreaded vs build config/machine Y seems to run parallelized) was a red herring.

    The build process consists of several stages like was illustrated above. Some of those stages are parallelized (steps 5,6 above come to mind at least), and others are not.

    So it would not give a correct conclusion to look at task manager for a short period of time during the link and reason if the link was parallelized or not, that depends on which exact stage the link process was going on when taking a peek.

    In particular, the LLVM LTO procedure (step 3) is not parallelized. So if that was running slow, then it would look like most of the link overall was running singlethreaded.

    Overall, independent of the upcoming added option to disable LTO when targeting Runtime Speed and Disk Size, the fastest current build setting that we know of is to

    a) do a Development build with WebAssembly.Table and BigInt language features enabled,

    or if that is not feasible (maybe some feature requires iterating on Release builds), the second fastest build is to do

    b) a Release build with Code Optimization set to "Build Times", and with WebAssembly.Table and BigInt language features enabled.

    The LTO disabled variant of Runtime Speed and Disk Size builds will still be expected run slower than both a) and b) above, since Runtime Speed and Disk Size builds both activate more optimizations than the Build Times setting.
     
    MousePods and KamilCSPS like this.