Huge memory consumption on iOS while loading Javascript module

Hi,

I was attempting to use a javascript library called libsodium.js [https://github.com/jedisct1/libsodium.js] with fusetools as encryption library. This library is originally writen in C but ported to javascript through emscripten compiler with asm.js generated code. I’ve been using this library for a while on my hybrid mobile apps (iOS and Android) and works just fine.

For that I’m trying to replicate that functionality (which is very crucial for my apps) with fusetools and hoping it would work as in the hybrid apps (with the assumption that this library would work without browser). The local test and android test shows this library work as expected, the functionality and the resource consumption (CPU and Memory) is quite normal as the hybrid apps. But in the iOS device, I was experiencing an issue, the memory is climbing quickly and reach more 300MB and finally had to closed by the iOS with memory warning exception. At first I thought that this library is not compatible with iOS javascript engine, but then I tried to execute it with the simulator and behaves consistently with my iPhone, the memory usage was expanding quickly, but this time the memory warning wasn’t throwed though exceed 1GB, but the function work as in android or local preview.

I was trying to modify my test code and thought that some function call might causing this memory issue, but turns out this issue started when I put require('libsodium.js') regardless I call a method / function or just do nothing.

I know that this kind of functionality better be implemented in Uno code, but the effort for porting the code will be huge, unless Uno can work with pure C code (android and iOS should be able to share this code), but I haven’t see any example or guide to work with pure C code.

Anyone could take a look what is going on here? , if it’s bug then I’ll wait for the fix or workaround but if it’s limitation then I’ll have to find an alternative solution (the code is actually working, just causing huge memory jump)

Hi!

Sorry to hear that. Does this happen in preview, export or both?

If the problem is specific to preview, it will probably be a lot better when you upgrade to Fuse 0.20. A lot of leaks and quirks around javascript modules has been cleaned up there. If that version isn’t out yet by the time you are reading this, you can join #pre-release-testing channel on our slack to get early access.

Hi,

It’s both, but in export the memory consumption is not as high as in preview mode,it’s reach 800MB though, and the CPU is also reach 100% when running the code

Thanks for the quick response

Best Regards

I know that this kind of functionality better be implemented in Uno code, but the effort for porting the code will be huge, unless Uno can work with pure C code (android and iOS should be able to share this code), but I haven’t see any example or guide to work with pure C code.

Uno can work with C code, but yeah, we’re thin on the docs/examples on how to work with that.

However, there is no reason why it shouldn’t work as JS/Emscripten.

Have you tried running CPU profiling on iOS and see why it is using all that CPU?

Hi Anders,

I was just trying 0.2.0 pre-release but it was no difference, still experiencing similar issue. And here what it looks like when I run profiler on it (it’s not all)

Bytes Used    Count        Symbol Name
 482.98 MB      89.0%    25324         thread_start
 482.98 MB      89.0%    25324          _pthread_start
 482.98 MB      89.0%    25324           _pthread_body
 482.68 MB      88.9%    24578            invoke_delegate(void*)
 481.66 MB      88.7%    24577             uDelegate::InvokeVoid()
 481.66 MB      88.7%    24577              g::Uno::Threading::POSIXThread__ReleasingLauncher__Run_fn(g::Uno::Threading::POSIXThread__ReleasingLauncher*)
 481.66 MB      88.7%    24577               g::Uno::Threading::POSIXThread__ReleasingLauncher::Run()
 481.66 MB      88.7%    24577                uDelegate::InvokeVoid()
 481.66 MB      88.7%    24577                 g::Fuse::Reactive::ThreadWorker__Run_fn(g::Fuse::Reactive::ThreadWorker*)
 481.66 MB      88.7%    24577                  g::Fuse::Reactive::ThreadWorker::Run()
 480.73 MB      88.6%    22855                   uDelegate::InvokeVoid()
 480.73 MB      88.6%    22802                    g::Fuse::Reactive::EventBinding__CallClosure__Call_fn(g::Fuse::Reactive::EventBinding__CallClosure*)
 480.73 MB      88.6%    22802                     g::Fuse::Reactive::EventBinding__CallClosure::Call()
 480.72 MB      88.6%    22786                      g::Fuse::Scripting::Function::Call(uArray*)
 480.72 MB      88.6%    22786                       g::Fuse::Scripting::JavaScriptCore::Function__Call_fn(g::Fuse::Scripting::JavaScriptCore::Function*, uArray*, uObject**)
 480.72 MB      88.6%    22786                        g::Fuse::Scripting::JavaScriptCore::JSValue::CallWithArguments(uObject*, uArray*)
 480.72 MB      88.6%    22786                         g::Fuse::Scripting::JavaScriptCore::JSValue::CallWithArguments(uObject*, uArray*)::$_0::operator()(objc_object*, id<UnoArray>) const
 480.72 MB      88.6%    22786                          -[JSValue callWithArguments:]
 480.72 MB      88.6%    22786                           JSObjectCallAsFunction
 480.72 MB      88.6%    22786                            JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&)
 480.72 MB      88.6%    22786                             JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&)
 480.72 MB      88.6%    22786                              JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*)
 480.72 MB      88.6%    22786                               vmEntryToJavaScript
 480.67 MB      88.5%    22323                                llint_entry
 480.67 MB      88.5%    22323                                 JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*)
 480.67 MB      88.5%    22323                                  long long JSC::APICallbackFunction::call<JSC::ObjCCallbackFunction>(JSC::ExecState*)
 480.67 MB      88.5%    22323                                   JSC::objCCallbackFunctionCallAsFunction(OpaqueJSContext const*, OpaqueJSValue*, OpaqueJSValue*, unsigned long, OpaqueJSValue const* const*, OpaqueJSValue const**)
 480.67 MB      88.5%    22323                                    JSC::ObjCCallbackFunctionImpl::call(JSContext*, OpaqueJSValue*, unsigned long, OpaqueJSValue const* const*, OpaqueJSValue const**)
 480.67 MB      88.5%    22323                                     -[NSInvocation invoke]
 480.67 MB      88.5%    22323                                      __invoking___
 480.67 MB      88.5%    22323                                       ___ZZN1g4Fuse9Scripting14JavaScriptCore7JSValue26ValueWithCallbackInContextEP9uDelegateP7uObjectENK4$_24clEU13block_pointerFPU19objcproto9UnoObject11objc_objectP11objc_objectPU18objcproto8UnoArray11objc_objectESC__block_invoke
 480.67 MB      88.5%    22322                                        ___ZZN1g4Fuse9Scripting14JavaScriptCore7JSValue26ValueWithCallbackInContextEP9uDelegateP7uObjectENK4$_25clEPU19objcproto9UnoObject11objc_object_block_invoke
 480.67 MB      88.5%    22322                                         uDelegate::Invoke(unsigned long, ...)
 480.67 MB      88.5%    22322                                          uDelegate::Invoke(uTRef, void**, unsigned long)
 480.67 MB      88.5%    22322                                           uInvoke(void const*, void**, unsigned long)
 480.67 MB      88.5%    22322                                            g::Fuse::Scripting::JavaScriptCore::Marshaller__CallbackExceptionHandler__Call_fn(g::Fuse::Scripting::JavaScriptCore::Marshaller__CallbackExceptionHandler*, uObject*, uArray*, uObject**)
 480.67 MB      88.5%    22322                                             g::Fuse::Scripting::JavaScriptCore::Marshaller__CallbackExceptionHandler::Call(uObject*, uArray*)
 480.67 MB      88.5%    22322                                              uDelegate::Invoke(unsigned long, ...)
 480.67 MB      88.5%    22322                                               uDelegate::Invoke(uTRef, void**, unsigned long)
 480.67 MB      88.5%    22322                                                uInvoke(void const*, void**, unsigned long)
 480.67 MB      88.5%    22322                                                 g::Fuse::Scripting::ScriptModule__RequireContext__Require_fn(g::Fuse::Scripting::ScriptModule__RequireContext*, uArray*, uObject**)
 480.67 MB      88.5%    22322                                                  g::Fuse::Scripting::ScriptModule__RequireContext::Require(uArray*)
 480.67 MB      88.5%    22322                                                   g::Fuse::Scripting::ScriptModule__RequireContext::Require1(uString*)
 240.33 MB      44.2%    11135                                                    g::Fuse::Scripting::Module::Evaluate1(g::Fuse::Scripting::Context*, uString*)
 240.33 MB      44.2%    11127                                                     g::Fuse::Scripting::Module::Evaluate(g::Fuse::Scripting::Context*, g::Fuse::Scripting::ModuleResult*)
 240.33 MB      44.2%    11127                                                      g::Fuse::Scripting::ScriptModule__Evaluate_fn(g::Fuse::Scripting::ScriptModule*, g::Fuse::Scripting::Context*, g::Fuse::Scripting::ModuleResult*)
 240.33 MB      44.2%    11125                                                       g::Fuse::Scripting::Function::Call(uArray*)
 240.33 MB      44.2%    11125                                                        g::Fuse::Scripting::JavaScriptCore::Function__Call_fn(g::Fuse::Scripting::JavaScriptCore::Function*, uArray*, uObject**)
 240.33 MB      44.2%    11116                                                         g::Fuse::Scripting::JavaScriptCore::JSValue::CallWithArguments(uObject*, uArray*)
 240.33 MB      44.2%    11116                                                          g::Fuse::Scripting::JavaScriptCore::JSValue::CallWithArguments(uObject*, uArray*)::$_0::operator()(objc_object*, id<UnoArray>) const
 240.33 MB      44.2%    11116                                                           -[JSValue callWithArguments:]
 240.33 MB      44.2%    11116                                                            JSObjectCallAsFunction
 240.33 MB      44.2%    11116                                                             JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&)
 240.33 MB      44.2%    11116                                                              JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&)
 240.33 MB      44.2%    11116                                                               JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*)
 240.33 MB      44.2%    11116                                                                vmEntryToJavaScript
 240.33 MB      44.2%    11116                                                                 llint_entry
 240.33 MB      44.2%    11116                                                                  0x39a3f99b39
 240.33 MB      44.2%    11116                                                                   llint_entry
 240.33 MB      44.2%    11115                                                                    JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*)
 240.33 MB      44.2%    11115                                                                     long long JSC::APICallbackFunction::call<JSC::ObjCCallbackFunction>(JSC::ExecState*)
 240.33 MB      44.2%    11115                                                                      JSC::objCCallbackFunctionCallAsFunction(OpaqueJSContext const*, OpaqueJSValue*, OpaqueJSValue*, unsigned long, OpaqueJSValue const* const*, OpaqueJSValue const**)

And here is the list of heaviest stack trace

  88 libsystem_pthread.dylib  482.98 MB     thread_start
  86 libsystem_pthread.dylib  482.98 MB     _pthread_body
  85 sodium  482.68 MB     invoke_delegate(void*) include/posix_thread.h:15
  72 sodium  480.72 MB     g::Fuse::Scripting::JavaScriptCore::JSValue::CallWithArguments(uObject*, uArray*)::$_0::operator()(objc_object*, id<UnoArray>) const /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.JSValue.mm:216
  71 JavaScriptCore  480.72 MB     -[JSValue callWithArguments:]
  59 CoreFoundation  480.67 MB     __invoking___
  58 sodium  480.67 MB     ___ZZN1g4Fuse9Scripting14JavaScriptCore7JSValue26ValueWithCallbackInContextEP9uDelegateP7uObjectENK4$_24clEU13block_pointerFPU19objcproto9UnoObject11objc_objectP11objc_objectPU18objcproto8UnoArray11objc_objectESC__block_invoke /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.JSValue.mm:578
  39 sodium  240.33 MB     g::Fuse::Scripting::JavaScriptCore::JSValue::CallWithArguments(uObject*, uArray*)::$_0::operator()(objc_object*, id<UnoArray>) const /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.JSValue.mm:216
  38 JavaScriptCore  240.33 MB     -[JSValue callWithArguments:]
  24 CoreFoundation  240.33 MB     __invoking___
  23 sodium  240.33 MB     ___ZZN1g4Fuse9Scripting14JavaScriptCore7JSValue26ValueWithCallbackInContextEP9uDelegateP7uObjectENK4$_24clEU13block_pointerFPU19objcproto9UnoObject11objc_objectP11objc_objectPU18objcproto8UnoArray11objc_objectESC__block_invoke /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.JSValue.mm:578
  11 sodium  240.33 MB     g::Fuse::Scripting::ScriptModule__RequireContext::Require1(uString*) /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.g.cpp:3743
  10 sodium  240.33 MB     g::Fuse::Scripting::Object::Item(uString*) include/Fuse.Scripting.Object.h:38
   9 sodium  240.33 MB     g::Fuse::Scripting::JavaScriptCore::Object__get_Item_fn(g::Fuse::Scripting::JavaScriptCore::Object*, uString*, uObject**) /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.g.cpp:734
   8 sodium  240.33 MB     g::Fuse::Scripting::JavaScriptCore::Marshaller::Wrap(uObject*) /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.g.cpp:616
   7 sodium  240.33 MB     g::Fuse::Scripting::JavaScriptCore::JSValue::IsExternal(uObject*) /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.JSValue.mm:320
   6 sodium  240.33 MB     g::Fuse::Scripting::JavaScriptCore::JSValue::IsExternal(uObject*)::$_7::operator()(objc_object*) const /Users/sahalzain/Workspace/Fuse/sodium/build/iOS/Debug/src/Fuse.Scripting.JavaScriptCore.JSValue.mm:322
   5 JavaScriptCore  240.33 MB     -[JSValue toObject]
   0 libsystem_malloc.dylib  239.98 MB     malloc_zone_calloc

Not sure what does it means

Thanks for reporting, we have created an internal issue to investigate this. Stay tuned.

Do you have a reproduction-case I can test with?

Hi,

You might try this test case project

https://github.com/zean00/fuse-sodium-test

Thanks. I have a fix for this issue, but it’s probably too late to get it into the 0.20-release.

Actually, we re-considered, and this fix will make it into 0.20.

Perfect :slight_smile: , looking forward for the official release