-
Notifications
You must be signed in to change notification settings - Fork 632
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
Documenting memory behaviours and leak detections #1518
Comments
We are definitely interested in providing documentation about the observable memory behavior. However what you are describing doesn't really align with that - we would like to understand the behavior you are describing. None of these things are supposed to happen: memory should not remain the same data is freed. Also, allocation should not accumulate exponentially. We have not actually observed what you are describing and don't have an explanation for it. In #982 we asked for some data. It would be very useful to see the values returned by getInstrumentedStats() in sequence, in each frame and how they change, along with the number of alive host objects at the same time. BTW, there is documentation on "Memory Profiles", although some minor details might be out of date: https://github.com/facebook/hermes/blob/main/doc/MemoryProfilers.md |
This is a great question. in #982 once I noticed that they were no leaks indeed, I wasn't sure which useful data points I could provide to you that could be useful. would a lot of Please let me know what kind of scenario, input, output data would be perfect for you. |
The behaviour you're observing is pretty unexpected, so we're eager to learn more.
We have also previously seen the allocator on macOS/iOS retain a large amount of excess memory even after allocations are freed, but I would not expect memory consumption to be increasing exponentially over time. |
Thank you for following up on this.
|
To confirm, you're seeing elevated memory consumption in both the performance monitor and in the instruments panel?
It would be interesting to see the release mode results. A disparity between dev and release modes would definitely be an interesting data point.
Yes, that would be fine. Depending on the time scale over which you see the rise in memory consumption, you may want to log more frequently than that so we have enough visibility into the memory pattern. Having extra data will only help. |
Hoping this helps. I believe this issue is related to our app's frequent crashes. Shopify/react-native-skia#2675 HermesInternal.getInstrumentedStats() every second before crash. |
Hey @dev-john-nguyen, according to the Hermes stats, Hermes is only managing 20MB of memory. Could you share more about why you believe Hermes is responsible for the elevated memory consumption? |
@dev-john-nguyen If your app has multiple Hermes runtime instances, could you share the output of |
@neildhar I'm not entirely sure if Hermes is the cause of the elevated memory consumption, but I’d like to help identify the cause and hopefully help us work towards a solution. As far as I know, the app doesn’t spin up multiple Hermes runtime instances, unless it’s happening dynamically in certain scenarios I’m unaware of. Is there a way to confirm whether multiple Hermes runtime instances are running in the app? |
@dev-john-nguyen there are two possible ways that I can think of this being related to Hermes:
One way to know when a Hermes runtime is created is to put a breakpoint with a native debugger in |
So it looks like reanimated is spinning up another Hermes runtime instance. Here's getInstrumentedStats for both instances until crash. (Edited posted the right stats) |
@dev-john-nguyen thanks for collecting this data so quickly! Unfortunately, it looks like neither of the runtimes owns a lot of memory. You can look at Ignoring the possibility of a catastrophic bug in Hermes (this is always theoretically possible, but I don't really see evidence for it), the only other explanation is that there is native memory that is not reported to the VM. I think you can use Instruments to see where this memory is being allocated. See this link (and particularly the "check the Malloc Stack box in the Diagnostics area" part): https://developer.apple.com/documentation/xcode/gathering-information-about-memory-use . |
@dev-john-nguyen another experiment you should run is to invoke You should probably do it separately on the two runtimes. |
Hi, @dev-john-nguyen Can you verify me? |
@tmikov I generated a memory graph report, and it appears to have detected a few leaks related to Hermes. I'm not very familiar with the tool, but let me know if you need more information, and I can try to provide it. |
@fatiherdogan01 |
@tmikov I invoked gc every second on both runtimes and it didn't help much. Pretty much still has the same behavior. Memory usage drops slightly and then stagnates. |
@dev-john-nguyen So, let's recap:
I think this is very strong evidence that this is not memory managed or leaked by Hermes, directly or indirectly. So, if Hermes is not allocating the 1.9GB, you need to identify who is. 1.9GB is quite a lot of data, so hopefully it should not be that difficult. By looking at all allocations before the crash, you should be able to get some idea of what the majority are. Are they malloc() for example? (Again, there is always a theoretical possibility that Hermes has a catastrophic bug, so we can never completely exclude that, but either way we need to find out where the data is allocated) |
The comments in this issue seem to support the idea that it would be more scalable to build comprehensive documentation to support library developers, rather than trying to address every question individually. On my side, I am in the process of migrating to Nitro modules and will report back on the observable behaviors I encounter. |
Regarding React Native Skia and WebGPU, I have often been confused about the observable memory allocations in these libraries. But even worse, we are genuinely struggling to explain these behaviors to our clients (see #982), who believe that our libraries are leaking memory.
I think it’s fair to say that many developers, in various situations, are under the impression that Hermes is leaking memory, even though it is not.
The goal of this issue is to create a documentation page that explains the current observable memory behavior (so we can share that information with our clients) and shows how to factually check whether a library/app is leaking memory.
Is there interest in such an initiative?
Here’s a recent example: As mentioned in #982, I was under the impression that RN WebGPU was leaking memory. I spent a substantial amount of time debugging, only to confirm that all objects are eventually deleted. Yet, the allocated memory stays the same and keeps growing. The demo on iOS in dev mode goes like this:
We allocate a bunch of objects, and after a certain time, they are all deleted. However, the allocated memory in the performance monitor remains the same. In the second cycle, many more objects are allocated before deletion (thus, allocated memory increases), and this exact pattern continues, creating an almost exponential memory allocation over time.
I assumed this behavior in dev mode is "okay." However, our clients are experiencing very similar behavior, and I’m not sure what to tell them since I’m not even sure myself what’s going on.
I hope this makes sense.
The text was updated successfully, but these errors were encountered: