Search Unity

WebAssembly blog post

Discussion in 'Web' started by Marco-Trivellato, Aug 15, 2018.

  1. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    kognito1 likes this.
  2. kognito1

    kognito1

    Joined:
    Apr 7, 2015
    Posts:
    331
    Great post, so kind of the opposite question I had before, what is the detriment of setting a very small initial memory size for wasm only builds? I made a quick test build with memory set to 16 MB and it seems to successfully run our applications (spot checking...). When "webassembly only" is selected, could the option to "set" memory simply go away (i.e. could Unity set the memory to something like 16 MB and automatically grow it to max)?
     
  3. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    It's a good question.
    The only reason you may want to set a higher value is if you want to avoid Heap growth. Based on what we have seen so far, resizing is fast so it should not be a problem. However, considering this is a new feature, we will wait before disabling Memory Size when deploying Wasm-only. If everything goes well, we can make this change in the 2019 cycle.

    On this topic, would you like to be able to set the maximum value via UI (instead of passing WASM_MEM_MAX to emscripten) ?
     
    game_apps likes this.
  4. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    This is super exciting news, the number one issue we have with WebGL is it running out of memory all the time and having to make a compromise between setting an initial large memory size that might not be achievable or setting it too low and having it crash out of memory.
    Is this going to stay a 2018.2 feature or is there any chance this option to target wasm only with the dynamic heap will make it's way back into 2017 ?
     
  5. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    We are not going to backport it because it's a new feature and we don't want to impact stability of 2017 LTS.

    However, I believe someone posted here in the forum that they managed to use "-s ALLOW_MEMORY_GROWTH=1" (via emscriptenArgs) when targeting WebAssembly. You could try that and see if you run into any problem.
     
  6. kognito1

    kognito1

    Joined:
    Apr 7, 2015
    Posts:
    331
    Thank you for the explanation!

    We just had a discussion about the topic this morning. And the answer is...maybe (but probably not). :D

    When "actual clients" are using the application, I don't see why one would ever want to set a predefined limit. If you (accidentally) go over the predefined limit, wouldn't you rather have a "chance" that the client could still allocate the extra memory anyways? "Erroring out" for no reason seems counterproductive to me in this circumstance.

    However the concern is during production. Up until this point we've tried hard to stay within a 512MB heap size. Before 2018.2 this was obviously very easy to "enforce" on the production team. If they went over the limit the binary would simply crash. The problem here (as you identified in the blog post) is now it's very easy for production to accidently blow through this limit and still "work" on their high-end machines. If caught late during the production cycle this would lead to some big headaches for sure. So the question is now what's the best path to enforce the limit on production?

    After discussing it a little bit, we came up with two possible solutions for this workflow problem (so far):

    1) Have the production team constantly test with a [lowest end device that we still officially "support"]. The pro here is production team can still build and test applications with the exact same binary that end users will be using. The con obviously is this method is prone to "human error" (Can we trust production teams to vigilantly test low end devices throughout the production cycle for each project? This is a bit of a leap of faith.). In this case the UI option (or setting a predefined limit in general) would be of little-to-no value.

    2) Whenever we make a build, automatically make another one that sets a predefined max of 512 MB (I'm operating under the assumption that wasm is still not like asm.js where you can just change memory on a whim in the .json file). We actually do this already for generating development builds (with exceptions on) so it wouldn't be difficult to integrate in our pipeline. The cons would be *technically* production would be testing against a binary that end users are not using and we'd be increasing build times non-trivially (we could live with both though). However even with this option there's little-to-no value in exposing the "predefined limit" in the UI since it would be scripted anyways.

    Where having a UI could make sense is what I would consider the "ideal case" (this would probably require a non-trivial effort on Unity's part):

    Unity would still not set a predefined limit for wasm but implement their own "internal predefined limit" and crash (or something) when that threshold was reached. That way we could simply pass in a value through the .json file (or whatever) that could dynamically set the max. For "actual clients" there would be no predefined limit set, but for production we would set a limit of 512 MB. In this situation the UI option would essentially function like it does for asm.js today. A default value that you could change at will after the fact.

    Anyways sorry for the long post; it's an interesting workflow problem for sure. FWIW our next release will be wasm only. :)
     
  7. JJJohan

    JJJohan

    Joined:
    Mar 18, 2016
    Posts:
    214
    I'd be curious to see if there was a more graceful way of handling the memory limit being reached - I've looked into a bit on the Emscripten GitHub page but thinking about it, it sounds like it would be near impossible due to the fact it's simply trying to allocate heap memory in its rawest form (besides preventative measures).

    Unfortunately we're dealing with Enterprise/government clients who often have 32-bit environments. The memory growth feature is great, except there's no guarantee that expanding the heap will succeed. Because there doesn't appear to be a way to query the maximum heap size up-front in Emscripten which makes it difficult to implement preventative measures, even though we can query the current memory usage without issue. The alternative is we have to always assume a maximum predefined limit (say 512mb) even if the user's browser is able to allocate beyond that limit which seems somewhat undesirable.
     
    Last edited: Aug 17, 2018
  8. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    That option doesn't seem to exist, how are they doing that?

    https://docs.unity3d.com/2017.4/Documentation/ScriptReference/PlayerSettings.WebGL.html
     
  9. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    One way I found is PlayerSettings.SetPropertyString but that's marked as obsolete in 2017.4
     
  10. JJJohan

    JJJohan

    Joined:
    Mar 18, 2016
    Posts:
    214
    Assuming you're talking about the emscriptenArgs - there's two ways:

    1. Modify the ProjectSettings/ProjectSettings.asset manually in a text editor (e.g. Notepad) and search for - EmscriptenArgs: then modify the entry i.e.

    webGLEmscriptenArgs: -s ALLOW_MEMORY_GROWTH=1

    2. Via script:

    UnityEditor.PlayerSettings.WebGL.emscriptenArgs = "-s ALLOW_MEMORY_GROWTH=1";
     
  11. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    I see some questions around doing this though that says it causes more issues than it solves as in order to increase the memory it needs to duplicate it all first, is that still the case?
    Also, I see in the 2018.2 version you have to be targeting wasm builds only, is that also true for this method, and if so how do you do that? Or does this switch only relate to the wasm part of the build?
     
  12. JJJohan

    JJJohan

    Joined:
    Mar 18, 2016
    Posts:
    214
    I've personally not experienced stability issues and have been using this without issue in 2017.3 and now 2018.1 however it's probably wise to say that if stability and official support from Unity is a concern it's probably better to simply use 2018.2 onwards. While this version basically injects the same flag, it's worth noting it uses a newer version of Emscripten which comes with a number of bug fixes in various areas.

    The actual memory growth process itself doesn't really appear noticeable during use of the application, however I can see it being a valid concern on 32-bit environments since it would most likely have to copy the existing heap to the larger one which would temporarily result in more than double the original size. In a 64 bit browser and OS this should not be an issue.

    Regarding wasm and asm.js support.. It does technically work for asm.js but I wouldn't recommend it as it comes at a performance cost and I believe browsers are actually beginning to remove support for memory growth on asm.js entirely. If you are targeting both asm.js and WebAssembly you'd probably have to create a separate build for each, one with and one without the flag. Again, Unity 2018.2 handles this for you which is quite convenient.
     
  13. monark

    monark

    Joined:
    May 2, 2008
    Posts:
    1,598
    Great, thanks for all the details!
    We'll give it a test out.

    UnityEditor.PlayerSettings.WebGL.emscriptenArgs = "-s ALLOW_MEMORY_GROWTH=1";
    So even though it's not in the help this does work in 2017 via a script.
     
  14. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    In general, if stability is a concern, we recommend to stay on a LTS release (currently it's 2017 LTS) which is going to be supported for 2 years after release.
    2018.2 belongs to the TECH stream, which usually bring a lot of new features and so the risk of new bugs.

    At the end of the day I think it depends a lot on your project and your schedule.

    For more information about LTS and Tech Stream, please refer to this blog post.
     
  15. kognito1

    kognito1

    Joined:
    Apr 7, 2015
    Posts:
    331
    Just a quick note, it seems like development builds require a minimum starting heap of 32MB (or maybe just our build does?) for reasons I don't quite understand. :p 16MB seems to work fine for non-development builds, but development builds immediately crash on startup. Not a big deal obviously but something I thought I'd share.
     
  16. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    Thanks for bringing this up. We will take a look.
     
  17. TheRoccoB

    TheRoccoB

    Joined:
    Jun 29, 2017
    Posts:
    54
    This is really cool--

    A lot of amateur devs have been having problems with this heap thing on the site I run for Unity WebGL. And I will definitely point them to to this article (use WASM for dynamic heap)! Seems like a very simple fix that will make a lot of people happy.

    Thanks Marco!

    -Rocco
     
    Marco-Trivellato likes this.
  18. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    769
    in the blog post you have a section on performance, but you don't provide a single number? is there some actual performance comparisons somewhere?
     
  19. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    A new blog post with performance comparison numbers is going to be published in the next few weeks :)
     
    andrzej_cadp and goldbug like this.
  20. Shadowing

    Shadowing

    Joined:
    Jan 29, 2015
    Posts:
    1,648
    Actually I left memory size at 256. So idk maybe i'll decrease that later. Either way how about the other thing about Web Assembly that no one here is talking about.
    ITS SOOOOOOOOOOOOOOOOOO FAST OMG!!!!.
    Its like a 4 second load time now. Incredible.
    Also it just feels better when its loading. Feels like a web page flipping now. As if the game engine isn't even in the background.

    Of course my game is just a canvas game but still its so nice to see Web GL on Unity has come this far finally.

    You will need to make an account if you want to test my game on how fast it loads.
    Registration is fast though. Theres a 7 day before you have to verify email.
    https://dakara.systemlords.26horses.com/
     
  21. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    It's live now.
     
    goldbug likes this.
  22. vb2s360

    vb2s360

    Joined:
    Oct 7, 2015
    Posts:
    34
    Thanks Marco, this is great.
     
  23. Kiori

    Kiori

    Joined:
    Jun 25, 2014
    Posts:
    161
    Hey Marco I clicked on the link in the recent post and it hanged basically. Nothing happened it just stood there, then I figured, I might as well reload the page, and then it loaded normally.

    It's not the first time I had these first time servicing bugs in Unity. You said in the post that you guys test it once it's cached, internally, for whatever reason. I hope you guys are not forgetting to test the first served delivery also, before anything is cached.

    Anyways that's my feedback. I just clicked on the link, using latest FF, nothing fancy.
     
  24. Dan_NextRevC

    Dan_NextRevC

    Joined:
    Apr 18, 2018
    Posts:
    19
    Awesome post, really glad to see Unity taking advantage of the most recent browser technologies and reducing load times to be really fast. Damn Firefox! Hoping to see that Unity engine initialization gets reduced further with the re-introduction of multithreading for the web.
     
  25. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    First time load time depends on build size and download speed so this time we decided to focus on second load. However, Wasm streaming instantiation allows the browser to compile while downloading, again something that has never been possible with asm.js...
    Soon there will be more news on this.
     
    Kiori likes this.
  26. Kiori

    Kiori

    Joined:
    Jun 25, 2014
    Posts:
    161
    The main issue for me was the bug, the fact that it hanged on load, not the load time per se.
    I meant this link btw: https://files.unity3d.com/marcot/benchmarks2018.2.5f1/
    But i hope you guys keep working on it. good luck!
     
  27. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    any info in the browser log? what version of Firefox? which OS?