CollisionProspect memory use
What happened?
There are a weird number of CollisionProspect objects when you have a minimal game. I think we can count it a bug.
And I think it causes a lot of GC calls as a result
It was tested with flame 1.21.0 (latest at the moment)
This is how the game looks like:
What do you expect?
I expect to have less amount of instances in my memory when I have a game with only 3 components.
How can we reproduce this?
- Please run the below code snippet it only adds a player (blue color) and 2 enemies (red color)
- Now the player moves along the x-axis to hit the enemies (they all have hitboxes).
- After a short time (4, 5 seconds) open the Devtools -> Memory, then you will see that we have more than 1k instances of
CollisionProspectobject
- Also I think the instances count of the other object (called
_OrderedSetIterator) is not reasonable
main.dart
import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
GameWidget(game: MemoryTestGame()),
);
}
class MemoryTestGame extends FlameGame with HasCollisionDetection {
@override
void onLoad() {
super.onLoad();
add(Player(Vector2(100, 200)));
add(Enemy(Vector2(200, 200)));
add(Enemy(Vector2(300, 200)));
}
}
class Player extends CircleComponent {
Player(Vector2 position)
: super(
radius: 30,
position: position,
paint: Paint()..color = Colors.blue,
anchor: Anchor.center,
);
late double _movingTo;
@override
Future<void> onLoad() {
add(CircleHitbox(
collisionType: CollisionType.active,
));
add(MoveByEffect(
Vector2(400, 0),
EffectController(
duration: 3,
infinite: true,
alternate: true,
),
));
_movingTo = 400;
return super.onLoad();
}
}
class Enemy extends CircleComponent {
Enemy(Vector2 position)
: super(
radius: 20,
position: position,
paint: Paint()..color = Colors.red,
anchor: Anchor.center,
);
@override
Future<void> onLoad() {
add(CircleHitbox(
collisionType: CollisionType.passive,
));
add(ScaleEffect.by(
Vector2.all(1.2),
EffectController(
duration: 0.5,
infinite: true,
alternate: true,
),
));
return super.onLoad();
}
}
What steps should take to fix this?
No response
Do have an example of where the bug occurs?
No response
Relevant log output
No response
Execute in a terminal and put output into the code block below
~ » flutter doctor -v neo@imans-mbp [✓] Flutter (Channel stable, 3.24.3, on macOS 15.0.1 24A348 darwin-arm64, locale en-US) • Flutter version 3.24.3 on channel stable at /Users/neo/Dev/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 2663184aa7 (5 weeks ago), 2024-09-11 16:27:48 -0500 • Engine revision 36335019a8 • Dart version 3.5.3 • DevTools version 2.37.3
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/neo/Library/Android/sdk • Platform android-34-ext8, build-tools 34.0.0 • ANDROID_HOME = /Users/neo/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314) • All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 16.0) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 16A242d • CocoaPods version 1.15.2
[✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2024.1) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314)
[✓] IntelliJ IDEA Community Edition (version 2024.2.3) • IntelliJ at /Users/neo/Applications/IntelliJ IDEA Community Edition.app • Flutter plugin version 82.0.3 • Dart plugin version 242.22855.32
[✓] VS Code (version 1.94.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.98.0
[✓] Connected device (4 available) • Iman’s iPhone (mobile) • 00008030-000E21EA0EA1802E • ios • iOS 17.6.1 21G93 • macOS (desktop) • macos • darwin-arm64 • macOS 15.0.1 24A348 darwin-arm64 • Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 15.0.1 24A348 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 130.0.6723.58
[✓] Network resources • All expected network resources are available.
• No issues found!
Affected platforms
All, macOS
Other information
I just tested it in my macOS
Are you interested in working on a PR for this?
- [ ] I want to work on this
Interesting, I thought we were pooling the prospect objects. I'll have a look tomorrow!
I've had a look, it works exactly like it should. :)
The pool size starts at 1000, and then there is a second pool for holding the last potentials which will slowly grow, but it will only ever be as big as the maximum amount of collision prospects you have in one frame. It never shrinks, but that is intentional so that it doesn't have to re-create the objects when it peaks the next time. So a trade-off between memory and speed. Since these pools only take up 48KB by default I don't think this will be a problem for anyone.
The amount of _OrderedSetIterator's is intereseting though, but that should be opened in a separate issue.
Just had a look at _OrderedSetIterator and that one isn't a problem either, turn on "Refresh on GC" in the devtools and you'll see that they are properly garbage collected.
Thanks for checking it It's good that we don't have a memory leak or something like that. I was worried about that.