-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Attaching many sized objects to NativeFinalizer #50537
Comments
After 1.5 hour..
|
On MacOS arm64 2.18.5 this reproduces: https://gist.github.com/dcharkes/352aee3d486c3bd5fba0b828ac3042df On MacOS arm64 version 2.17.5 stable (in Flutter), it becomes slower at a point, but around 100ms rather than 2000ms: https://gist.github.com/dcharkes/9b9e063dbb6d8859025c917085bc7612
On Flutter master it goes quickly out of memory: https://gist.github.com/dcharkes/b80cce1f1a1a91cf848581c9b8c3deb6 I do not believe I did any changes to native finalizers, so it might be GC changes related. @nielsenko can you reproduce this on Flutter master? |
The OOM seems to be caused by c9f0120. If I comment out the OOM, I can reproduce something similar that involves GC thrashing with a negative total external size. |
Will you investigate and fix @rmacnak-google ? |
Yeah, this feels like a GC-accounting issue rather than a finalizer issuer. |
Thanks @rmacnak-google ! |
With dart from flutter master (Dart SDK version: 2.19.0-424.0.dev on "macos_arm64"), I quickly hit OoM with
I have also setup the project with a flutter example. Again on flutter master
This time with
With stable I see the weird behaviour as before, also on flutter, but 300ms cliff instead of 2000ms for some reason:
|
We don't hit this if we implement our own NativeFinalizers with void handle_finalizer(void* isolate_callback_data, void* realmPtr) {
realm_release(realmPtr);
}
RLM_API void* realm_attach_finalizer(Dart_Handle handle, void* realmPtr, int size) {
return Dart_NewFinalizableHandle_DL(handle, realmPtr, size, handle_finalizer);
}
RLM_API void realm_dettach_finalizer(void* finalizableHandle, Dart_Handle handle) {
Dart_FinalizableHandle finalHandle = reinterpret_cast<Dart_FinalizableHandle>(finalizableHandle);
return Dart_DeleteFinalizableHandle_DL(finalHandle, handle);
} Where we are still using a non-zero size for |
…e incrementing external size. When a FinalizerEntry's target gets promoted, the associated external size needs to also get promoted. We were handling the cases where the FinalizerEntry itself was either already old or remained new, but not the case where it was promoted. Failing to promote the external size meant that when the finalizer was collected, external size was subtraced from old space that was still being attributed to new space, so the old space total external size became negative. TEST=ci Bug: #50537 Change-Id: Id2fe2d748311de73f04de367c9cd153d87b74ad1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272350 Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
I just ran into the |
There was a comment on https://dart-review.googlesource.com/c/sdk/+/272350 about cherry picking. But it looks like the CP was never done https://dart-review.googlesource.com/q/%22Add+missing+promotion%22 cc @rmacnak-google . |
…move race incrementing external size. When a FinalizerEntry's target gets promoted, the associated external size needs to also get promoted. We were handling the cases where the FinalizerEntry itself was either already old or remained new, but not the case where it was promoted. Failing to promote the external size meant that when the finalizer was collected, external size was subtraced from old space that was still being attributed to new space, so the old space total external size became negative. TEST=ci Bug: #50537 Change-Id: I83316636dea13415f38343212157c32f5ef19857 Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/272350 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/289941 Reviewed-by: Alexander Markov <alexmarkov@google.com>
I have created a barebone reproduction of an issue we first observed wrt. Realm.
You can find it on github here: https://github.com/nielsenko/weird
It basically allocates and leave as garbage a lot of
PointHandles
that holds aPointer<Point>
wherePoint
is a struct bound via ffi.In the ctor of
PointHandle
I allocate aPoint
struct and attach the pointer to aNativeFinalizer
to ensure the native memory is freed when the handle is GC'ed. On attach I setexternalSize : 16
which is important (I dont see the issue if II forget to setexternalSize
)When I allocate (and leave as garbage) a lot of
PointHandle
s in a loop, I see a drop in the speed of allocations after a while.I would expect the GC to kick in, clean out some handles, causing speed to degrade while it happens, but I would also expect the speed to recover after the GC has run. The latter does not seem to happen, at least not to the pre-first-gc speed.
Example output:
First row is number of objects (
PointHandle
+Point
) allocated, then total time, time since previous line, and last the current number of livePoint
structs - these are counted on the native side.Environment:
Dart SDK version: 2.18.4 (stable) (Tue Nov 1 15:15:07 2022 +0000) on "macos_arm64"
Flutter 3.3.8 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 52b3dc25f6 (2 weeks ago) • 2022-11-09 12:09:26 +0800
Engine • revision 857bd6b74c
Tools • Dart 2.18.4 • DevTools 2.15.0
The text was updated successfully, but these errors were encountered: