BabylonJS / BabylonNative

Build cross-platform native applications with the power of the Babylon.js JavaScript framework
MIT License
763 stars 132 forks source link

Demo projects take too much memory #1080

Closed ZhuoYitao closed 1 year ago

ZhuoYitao commented 2 years ago

Either the Android demo project or the iOS demo project takes more than 100MB memory. Considering they simply render a cube, the memory cost is too large. Is there any suggestion to reduce the memory usage?

P.S. I've changed some configs in 'Dependencies/bgfx.cmake/bgfx/src/config.h', such as the 'BGFX_CONFIG_MAX_DRAW_CALLS' definition, but the total memory keeps unchanged.

ZhuoYitao commented 2 years ago

Hi @bghgary, do you have any idea about this issue? Please let me know if I need to add more information.

ryantrem commented 2 years ago

Sounds related to #726 (or at least that issue probably has relevant context).

ZhuoYitao commented 2 years ago

https://github.com/bkaradzic/bgfx/issues/1715

Hi @ryantrem, bgfx does reserve a large amount of memory. Changing configs of bgfx can reduce the allocated heap. For example, modify the value of 'BGFX_CONFIG_MAX_DRAW_CALLS' in 'Dependencies/bgfx.cmake/bgfx/src/config.h' to '64' can reduce more than 60MB of heap allocation. Confusingly, the total memory usage is not changed.

bghgary commented 2 years ago

@ZhuoYitao Have you tried capturing a memory profile to see where the allocation is? The memory usage could be on the native side or maybe it's on the JS side.

ZhuoYitao commented 2 years ago

@bghgary I will have a look at it.

ZhuoYitao commented 2 years ago

Hi @bghgary,I notice that the LoadScript() method in the ScriptLoader class could cause a huge memory usage. When I comment out all lines in the "app:///Scripts/babylon.max.js" file (which means no meaningful JS code will be run), running loader.LoadScript("app:///Scripts/babylon.max.js") still takes about 88MB of memory. Could you have a try at optimizing the loader?

Here is more information about loading the commented "babylon.max.js" file:

  1. Running "m_responseString = std::string{static_cast<const char*>(data.bytes), data.length};" in "Dependencies/UrlLib/Source/Apple/UrlRequest.mm" takes about 25MB of memory.
  2. Running "NAPI_THROW_IF_FAILED(env, napi_run_script(env, Napi::String::New(env, source), sourceUrl, &result))" in "Dependencies/napi/napi-direct/source/env.cc" takes about 50MB of memory.
bghgary commented 2 years ago

Running "m_responseString = std::string{static_cast<const char*>(data.bytes), data.length};" in "Dependencies/UrlLib/Source/Apple/UrlRequest.mm" takes about 25MB of memory.

This one is interesting. Does this string not get released later? If not, then this is a bug.

Running "NAPI_THROW_IF_FAILED(env, napi_run_script(env, Napi::String::New(env, source), sourceUrl, &result))" in "Dependencies/napi/napi-direct/source/env.cc" takes about 50MB of memory.

This is normal, in the sense that babylon.max.js is a big file with everything in it. It is also the max file (i.e., it is not minified). This is what the Playground app does because it is expected that it can use any Babylon.js API similar to the web Babylon.js playground. Using the max file is just so that it's easier to debug the JS code. One quick thing you can do is change this to load the minified babylon.js instead which should reduce the memory immediately.

Typically speaking, for real apps, the build should be using a bundler (e.g., webpack) with tree-shaking and minification to reduce the size of the loaded JS file. That should reduce the amount of memory being consumed from this call. It will also reduce the memory being used from the former issue, but that string should be transient and not stick around.

ZhuoYitao commented 2 years ago

@bghgary Indeed, using the minified babylon.js can reduce the memory. But the reduced memory is still too large to embed Babylon Native into a mobile app. I guess there is memory leak(s) in the LoadScript() method.

bghgary commented 2 years ago

But the reduced memory is still too large to embed Babylon Native into a mobile app.

Yes, I just mean you can test it to see how much it affects memory. You should use a JS bundler with tree-shaking and minification if you want to deploy to production, just like you would for Babylon.js in a browser.

I guess there is memory leak(s) in the LoadScript() method.

I can't rule this out. If you can confirm this, that'll be helpful.

bghgary commented 1 year ago

@ZhuoYitao Are you still seeing issues with this? If so, please reopen.