Skip to content
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

Guidance on C# memory management #9916

Open
Theome opened this issue Sep 6, 2024 · 0 comments
Open

Guidance on C# memory management #9916

Theome opened this issue Sep 6, 2024 · 0 comments
Labels
content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features enhancement topic:dotnet

Comments

@Theome
Copy link

Theome commented Sep 6, 2024

Your Godot version:
Godot 4.3

Issue description:

I believe that it would be very helpful to add a section with general guidance for memory management in C#. There is already a section in the docs dedicated to memory management here, but it only discusses memory segmentation in general, and is aimed at developers who want to contribute to the development of the engine itself, not at users of the engine. The conclusion is:

However, in many studies and tests, it is shown that given enough memory, if the maximum allocation size is below a given threshold (...), segmentation will not be a problem.

My main question that I would like to see answered is: Does this apply to C#? If we're doing many small heap allocations, the garbage collector will eventually run. Even if memory segmentation is not an issue, could this cause performance issues?

I've found conflicting information online about the impact of such allocations on garbage collection and overall performance. Some sources suggest that modern garbage collectors handle these situations efficiently, but the Unity documentation explicitly says:

To get around [negative effects on performance], you should try to reduce the amount of frequently managed heap allocations as possible: ideally to 0 bytes per frame, or as close to zero as you can get.

I bumped into this issue when I found out that the Send method in C# of ENetPacketPeer requires a byte[] argument (see godotengine/godot#71727). This array must have the exact length of the network packet that I want to send, so this requires an allocation of a temporary array, and there is no way to work around this with a memory pool. Should this API be updated at some time to be more memory efficient, or is there a general consensus that the garbage collector is fast enough that we can afford to allocate these small arrays for every API call, in particular because those are short-lived allocations?

Other questions that I would like to see answered:

  • Are there situations where it makes sense to manually trigger garbage collection?
  • Are there recommendations for free tools to analyze memory allocations that run on macOS? Visual Studio is no longer supported on macOS, the Jetbrains tools require a monthly subscription (these tools are mentioned in the docs here) and Godot's built-in memory debugging tools appear to monitor only allocations made by the engine, so C# allocations cannot be analyzed.
  • Are there any benchmarks on how long garbage collection takes on common systems? For example: 5ms on current gaming PCs and 20ms on mobile devices. (These are made-up values; I have no idea of the actual figures).
  • If relevant: Are there "hidden" heap allocations that are easy to overlook, but might cause problems in the long run, for example the use of certain closures, boxing, string allocations etc.
  • C# has a few native classes for memory management such as ArrayPool<T> and MemoryPool<T>. When should these be used?

I understand that this is a very broad topic and it won't be possible to give definitive answers to these questions. However, what concerns me is this: If I continue making hundreds of slightly suboptimal design decisions during game development, what happens if I run into memory performance issues in one or two years that are possibly difficult to debug and pin down? Then I might be forced to do countless small refactorings all over the place - I want to avoid that.

In other words: We can tell a beginner programmer not to put all global state into one all-knowing singleton. Or before creating subclasses in their model, to try composition first. This advice will probably lead to better overall design decisions and more maintainable code. Can we say similar things about C# memory management in Godot projects?

@skyace65 skyace65 added topic:dotnet content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features labels Sep 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features enhancement topic:dotnet
Projects
None yet
Development

No branches or pull requests

2 participants