-
-
Notifications
You must be signed in to change notification settings - Fork 34
Promise.resolve and Promise.reject causes memory leak on iOS. #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@darind This part of PromiseProxy seems to be be the culprit: https://github.com/NativeScript/ns-v8ios-runtime/blob/92195e8f7c02aa50a97d686757e0b04070c78ef7/NativeScript/runtime/PromiseProxy.cpp#L18-L26 Replacing with
or commenting out the script in PromiseProxy entirely fixed the leak for me Any immediate ideas? |
The reason this code exists is to ensure the promise callbacks are always executed on the same thread where they are constructed. Though I don't quite understand the inner |
Not exactly clear what situation it becomes useful as long as V8 locking is used properly, and I'm not sure it works fully as intended using try-catch blocks in async functions (.catch() will get invoked on the same thread but I think the mechanics of try catch in terms of execution moving to the catch block are different) Anyway, I dug further, this triggers the same memory leak: let count = 0
function cb () {
++count
}
setInterval(() => {
let runloop = CFRunLoopGetCurrent();
for (var i = 0; i < 100; i++) {
CFRunLoopPerformBlock(runloop, kCFRunLoopDefaultMode, cb);
CFRunLoopWakeUp(runloop);
}
console.log(count);
}, 50); It's the cb being passed to CFRunLoopPerformBlock and how it's processed from there I believe... My guess would be that it's a challenge for the runtime to know when CFRunLoopPerformBlock is done invoking Is there a free some where to go with this, which is getting invoked as part of translating the cb so it can be invoked by ObjC: https://github.com/NativeScript/ns-v8ios-runtime/blob/8409f9af84de73e2cd00cbeebce3ba4b53431a6e/NativeScript/runtime/Interop.mm#L70 |
9721e19 resolves a leak which comes from the runtime handling the second arg to CFRunLoopPerformBlock, Lines 347, 348 and 350 in Line 61 in and (I think this might just be the actual call to new): So looks like the memory does have to do with wrapping the passed js function so it can be invoked like a regular ObjC block? Not sure where to go from here to solve this but I assume this effects any native function passed a JS function to a parameter that takes a ObjC block. |
@delaneyb, great job in pinpointing this issue! I have included your suggested fix for the SymbolLoader memory leak in the V8 update PR. After applying it, I was able to run your sample snippet without uncontrolled memory increase and Instruments showing no leaks: |
@darind Sounds awesome! Hopefully this fix will be released for the runtime soon as it is a critical issue for my companys app to work. |
@schnapzz we'll be releasing a pre-release later today! 🚀 Update: released v7.1.2-rc.0 |
The memory leak seem to be handled, but memory still seem to not be released. Using the same code as in the original issue post
instruments doesn't register leaks but memory still keep increasing and is never released. |
@schnapzz I guess one of the issues has been fixed - in the above scenario. Perhaps the PromiseProxy still needs some work. Depending on your use - it may be fine to roll with it as-is in the meantime, or perhaps you could use |
@rigor789 Thanks I'll test if it works with the downgraded version tomorrow when time allows for it. And thanks for all the attention :-) Update: Downgrading the iOS runtime to 6.5.4 seem to have solved our critical issue with the video download! It's now sent out for testing and it looks promising! |
The only noticeable memory leak triggered by my original snippet is patched by 9721e19. Unfortunately afterwards I discovered that when testing that patch on the original issue NativeScript/NativeScript#9151, the patch only fixed a tiny portion of the memory leaked (the rest I identified in #100 (comment)). This snippet accurately reproduces the eventual call made when Promises are resolved/rejected, causing the larger memory leak: setInterval(() => {
for (var i = 0; i < 100; i++) {
CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, () => {});
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
}, 50); The difference being passing The memory being leaked by each call to It's possible this has always been an issue and PromiseProxy which was introduced in the V8 build has made it obvious because it means memory is leaked every time a promise is resolved or rejected, as opposed to just when a plugin uses a native function that takes a block as an argument. PromiseProxy doesn't seem to be necessary in my app - my plugins all function fine without it's help making sure Promise chains continue executing on the same thread, but it would really be sweeping the problem under the rug to remove that. |
Together with 9721e19, these totally fix the memory leak for me: master...delaneyb:fix-JSBlock-leak There were definitely issues with:
Both of which my changes seem to fix. However I just noticed #83, which I assume my use of CFAutoRelease would basically revert 😪.... A PR with the fixes for 1. and 2. will do nothing without the CFAutoRelease or another solution which ensures the JSBlock actually gets released and disposed. |
Hello @delaneyb , I confirm that your commits in relation to this issue totally fix the problem both on Simulator and on real device. In the meantime, a big thank you! |
Ah, hold on a minute - perhaps #83 CAN be reverted when combined with these other 2 fixes, because prior to #83, the 2 other leaks I fixed would have still been occuring, so by taking all of the fixes together, everything including those issues from #83 should be solved! Let me just see what happens if I try to reproduce 83 with and without those 2 other fixes to confirm that it's stable only with all of them together... |
Nope, scratch that - been debugging with #83 in XCode for hours now with my fixes in place, way too confused to try explain what's going on but it's the last 2 arguments passed to https://github.com/nativescript-community/ui-image/blob/44ddd705e75f4a648afdf1b2c7b6e07f240c57ac/src/image.ios.ts#L532-L539 - eventually something happens and one or both of the functions passed through in ObjC point to NULL or junk addresses, which can be traced back to https://github.com/NativeScript/ns-v8ios-runtime/blob/8409f9af84de73e2cd00cbeebce3ba4b53431a6e/NativeScript/runtime/Interop.mm#L354 where |
Any update date on this? This is an issue in one of our production apps that makes heavy uses of promises to write to an sqlite database. The app keeps closing due to out of memory issues. I'm afraid I can't help with objective-c though :( |
I've had success by downgrading to iOS runtime v. 6.5.4 whilst this issue is being edged out. This runtime version works with N{7} and have no memory leak issues. |
Is there any news in regards to this issue? |
* fix: don't allocate persistent empty objects * fix: Blocks memory leak (#100) * feat: drop custom WeakRef implementation & use built-in * fix: free allocated memory in ReferenceWrapper * fix: DictionaryAdapter Hanging References (#114) * Clean up hanging references before deallocating Reduces total dictionary related memory leaks by 36% * fix * chore: more leak fixes * fix: only release enumerator_ when set (#117) * fix: handle methods with pointer type params fixes #109 * fix: referenceWrapper memory leak & CString leak * refactor: ReferenceWrapper dispose to be managed internally * fix: pre-allocate memory even for empty values * fix: undo invalid fix (needs a different way) Co-authored-by: Darin Dimitrov <darin.dimitrov@gmail.com> Co-authored-by: Bryse Meijer <brysem@users.noreply.github.com> Co-authored-by: logikgate <nick.fredricks@flypaper.com>
To those who haven't seen the youtube updates, it seems that there might be a fix to this issue when {N} updates in august. Crossing my little fingyes. |
Is there any news related to this issue? |
Simply referencing another issue posted on the Nativescript repo but it seem to be an issue with the v8 ios runtime so I'll post it here as it seem a very important issue to be fixed.
NativeScript/NativeScript#9151.
The text was updated successfully, but these errors were encountered: