NativeScript / ios-jsc

NativeScript for iOS using JavaScriptCore
http://docs.nativescript.org/runtimes/ios
Apache License 2.0
298 stars 59 forks source link

Measuring Memory / running GC #560

Open NathanaelA opened 8 years ago

NathanaelA commented 8 years ago

I'm looking for some commands that can get me the following information;

  1. The currently running memory usage
  2. Running a GC
  3. A full heap snapshot to see what is being retained after a GC.

I can do all three of these easily in Android. But I'm not seeing anything accessible in iOS to get the same information. 1 & 2 are the most important, 3 is a nice feature..

Any pointers would be appreciated...

jasssonpet commented 8 years ago

Hey @NathanaelA,

You can view the memory of your running application in the Xcode Debug Monitor or you can get more detailed information with the Allocations Monitor in Instruments. Here is a more detailed explanation on how to do that: https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started.

Regarding your second question - you can set the JSC_logGC environment variable to log GC activity in the standard output of your running app (here is how). This will give you information like the following:

[GC: 3373 kb => EdenCollection, Did copy, 2958 kb, 1.029785 ms]
[GC: 4566 kb => FullCollection, Skipped copying, 4304 kb, 1.661865 ms]
[GC: 6380 kb => EdenCollection, Did copy, 6067 kb, 1.353027 ms]
[GC: 6736 kb => FullCollection, Skipped copying, 5914 kb, 2.298096 ms]

And for your last question - I'm afraid that there is no easy way to view all the objects in the heap with our JavaScriptCore build.

Let me know if that works for you 😄

NathanaelA commented 8 years ago

Thanks that gave me a way to go. Not as precise as Android but a direction. Android I can console.log("Memory used: ", gmu() ); gc(); console.log("Now used:", gmu());

For 2, I was actually looking for what you guys did with the __collect command, which didn't really seem to do anything, so I assume the GC is already being called frequently or when going into a idle period where nothing is ran (i.e. waiting for user input)

  1. That is a bummer, I can easily look at the entire GC chain & roots and what variables are allocated to and what is keeping them in memory in v8. Nothing like that available for JSC?

Do you know if __collect actually does anything, and I assume their is no command like 1 that I can run from inside the JS to get total memory used.

mn-martin commented 7 years ago

Do you know if __collect actually does anything, and I assume their is no command like 1 that I can run from inside the JS to get total memory used.

I'm interested in this as well. Can't seem to find any information about that __collect call.

NathanaelA commented 7 years ago

@mn-martin - Anything that starts with __ is an internal command and you won't find any documentation on them anywhere probably. From my testing it doesn't appear to do anything or maybe all it does is schedule an GC. But that was too late to see what effected what... All my tests did not show any real differences with using or not using it. iOS's JavaScriptCore doesn't have the cool internal stats tools that Android's v8 does.

mn-martin commented 7 years ago

@NathanaelA Well I can tell you at least one thing about __collect. It effectively stops my app from eating up all memory quickly by navigating between webviews back and fourth. It keeps the memory at a constant level when calling it from a navigatedFromEvent. My memory consumption stays at ~300MB (monitoring with Xcode) while without making these calls it is raising up to 1.2 GB until ARC kicks in. I managed to navigate quick enough to make the App crash before ARC has a chance to save me. That's why I started investigating.

Calling utils.GC() on the navigatedFromEvent seems to block the UI on Android during the navigation which is very bad. Anyways there seems to be better options like tuning the Garbage Collectors with the package.json. See: https://docs.nativescript.org/runtimes/android/advanced-topics/memory-management

I also did some testing calling utils.GC() on worker threads. It seems to have no effect at all on the iOS platform but it allows you to explicitly trigger garbage collection without blocking the UI on Android.

NathanaelA commented 7 years ago

@mn-martin - Cool; maybe it wasn't working last year; because I didn't see any differences when I was attempting to try and figure out memory usage. Thanks for the heads up that it actually does work now. I'll have to revisit my test bed on iOS...

GC() yeah, will freeze whatever thread you are on, however, I'm not sure if calling it on the worker thread will really effect the main thread... Each worker has it's own V8 engine running; so a GC in a worker I don't believe will effect the primary thread's v8 unless you have some of the v8 GC tuning that you linked above where the v8 (worker) -> Java (global) -> v8 (main). But then in that case the main v8 thread will still freeze while it is cleaning memory it owns as GC always freezes the thread so that JS can't make any allocations/de-allocations while it is cleaning.

mn-martin commented 7 years ago

@NathanaelA Thanks for clarification about running GC() within workers. Really interesting stuff :-)

altunyurt commented 6 years ago

@NathanaelA

Android I can console.log("Memory used: ", gmu() ); gc(); console.log("Now used:", gmu());

Could you clearify what gmu is? I'm having a hard time tracking where the memory usage skyrockets during runtime and i guess such thing would very well be handy.