-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
set MaxDirectMemorySize, reconsider Xmx
default size
#4948
Comments
MaxDirectMemorySize is for the memory allocated for NIO related to serilization/deserilization and network communication. maybe 1G should be a good safe value? |
We also use directbuffers for passing parameters to lwjgl exactly. Bullet - unknown |
Yeah, one of the things I haven't sorted out yet is which things do or don't use that type of Direct Memory buffer. Our documentation (or error-handling) for this should include instructions for how to tell if one of these limits is set too low. For example, when I set MaxDirectMemorySize too low, I get this error when trying to create a Metal Renegades game:
But if I set
(and, as that happened in another thread, the engine is still trying to chug along but isn't having a very good time of it.) |
As for defaults, I hope we can work with a default that's lower than a gigabyte! Given how low-res our textures are, a gigabyte is a huge amount of RAM. But yes, let's pick a default that seems to work for things as they are currently, and we can talk about optimization separately outside of this ticket. |
oh so that is all buffers declared with DirectByteBuffer. so when you allocate a DirectByteBuffer its a buffer that backs memory in xmx. that is all communication for networking, and any vertex data for meshes and I also believe for texture. |
I'm happy to have a look at any PRs that come up related to this. As the two open launcher PRs MovingBlocks/TerasologyLauncher#666 and MovingBlocks/TerasologyLauncher#667 touch the way it handles settings we may want to get them out of the way before we add new settings/features. |
Finally got around to read this. First of all:
Seems like we used to use 1.5G, but changed it to 3G in #4365 with the following reasoning:
Second, here's a few questions I have:
|
I'd say that the default memory settings should be sufficient to play our (supported) game modes with the default in-game settings. I would neither optimize for minimal nor maximal settings (either too restrictive, or too generous). We may want to add some hint in the menu that changing the view distance may require more memory. Depending on the exact behavior this may or may not lead to a (severe) crash. In case we have the chance to handle the out-of-memory error we can probably add a helpful message for the user that they might want to adjust the max memory setting if they are think their machine can handle it (exact wording of this "recommendation" is hard, though).
👍 +1 for this question. |
Ah, good questions!
The trouble comes from memory allocations with short lifetimes. Maybe very short, like something needed to render a single frame, or maybe a little less short, like a chunk that is loaded for a while but then should be un-loaded after the game has moved on. A memory allocator could re-use the space it assigned to old objects in old frames, but reclaiming memory takes work, so if it thinks it still has plenty of fresh memory available I guess it prefers to use that. Giving it an explicit limit forces it to do re-use earlier. But asking it to re-use old memory is only successful if there actually is discarded memory space available to reclaim. The limit must still be high enough for all the data it needs for that frame, or to load all the chunks necessary for a system's logic, or whatever. If it's not enough to fit all the objects that need to be live at once, then 💥
Yes.
I don't think this is a setting we can change at runtime. It'll have to be a "change settings and restart" kind of thing.
I think this becomes a "safer for who?" question. Lower values are safer for players on hardware with less RAM, or environments where less RAM is available for Terasology (b/c they're also running a browser and Discord and IntelliJ and gradle and Blender and whatever), game modes that don't have logic that spans many chunks or entities, or have a small play area (like the L&S arena). High values are safer for games with high render distances and a lot of stuff going on in-game, and in settings where the computer isn't being asked to do so much multi-tasking.
The answer to this begins with "look for all the code that imports I don't recommend getting in to that too deeply just yet. We'll likely want to do an optimization pass. Maybe we find more memory-efficient ways to do some things, but maybe they shift to a different memory allocation strategy, or they change when we upgrade to lwjgl 3.3 — oh, that was actually released as stable last month! That'll be good information to have, but I don't think it's necessary for the scope of this ticket. |
Okay, thank you for answering the questions and bringing some more light into this, @keturn I think @skaldarnar's comments
and
make sense here. The default JVM configuration should support the default game configuration. And if we restrict this to a (potentially low) default, issues resulting from this should be handled properly and it should be made clear to the user, what to do to improve the situation. So to find a suitable default, I guess we want to measure what's sufficient to play all our top 3 gameplays (+ core gameplay, although I think that's pretty much "included" in JS) with default in-game settings, correct? @keturn How did you measure / test this? Experiential, by specify a value and then see the game doesn't crash or using some kind of tooling? |
Yeah, my preliminary testing was not too formal. Start a new MR game, find a city, hang around long enough for it to grow a bit and have things spawn, etc. “See that the game doesn't crash” was the main assessment tool, but watching Java heap size and the process data size in JMC can give some indication of how much wiggle room there is. |
Okay, then to formalize this at least a tad, I'd like to brainstorm on things to test that give us some trust in that the default is a good one and doesn't blow up in our faces as soon as the first person actually tries to play one of the gameplays for more than a few minutes. |
And as a reminder, we are talking about choosing defaults for two values: |
Alright then, commencing brainstorming for first testing setup:
Tbh, for JS (other than walking around triggering chunk gen) and especially LaS I'm currently not so sure what memory-intense things to do would be 🤔 Do you have any ideas there @keturn @skaldarnar ? |
I think that's fine. Things we should take note of include:
I don't think we need to be super rigorous in this pass, but it'll be handy if we're later able to look back at our notes to answer "hey, did we test multiplayer with 2 people or 12?" |
Had a quick offline chat with skal about this and he mentioned
|
I started testing today and while the max heap configuration works properly, I'm having doubts about the MaxDirectMemorySize part... Irrespective of whether I set it in my I searched for a way to extend our memory debugging information with the runtime value of MaxDirectMemorySize to make sure I configured it correctly. Unfortunately it does not really seam possible to get this value without some hacky workarounds. |
I guess I'm not too surprised to hear it requires hacky workarounds to access at runtime, given that it's an implementation-specific flag set with It looks like one way to check is to add the
|
Sooo, did some singleplayer testing today (see #5025 for the utilized settings). 1. Test: CoreGameplay
2. Test: JoshariasSurvival
3. Test: MetalRenegades
|
From what I saw, memory consumption never went above 3G according to my resource monitor. Would be interesting to see how it behaves in multiplayer testing on the server. |
I'd been wondering if we could use this to get any insight in to what value it uses when we don't set it explicitly. The answer is: nope. PrintCommandLineFlags does show numbers for some things we weren't explicit about (e.g. ReservedCodeCacheSize), but when there is no explicit MaxDirectMemorySize, it's not printed among the flags at all. Checking (This is with Temurin OpenJDK 11.0.15.) |
Ran the same tests without the changes introduced in #5025 and that's the results:
OpenAL Error Logs (just fyi)
|
I discovered that setting the Java option
-XX:MaxDirectMemorySize
is effective at limiting the game's seemingly limitless hunger for memory outside the Java heap. I don't know what heuristic it uses by default, but my processes were regularly multiple gigabytes larger thanXmx
led me to believe they should be. (As measured by looking at the process in Linux and noting its Resident Set Size or data+stack size as in #4946).A value of
-XX:MaxDirectMemorySize=512M
was sufficient to run a single-player game of Metal Renegades with “Moderate” view distance (plus 6 LOD).Looking at how much of the process's memory is not in the Java heap also made me reconsider what value we use for that by default. We currently give it a whopping three gigabytes in development workspaces:
Terasology/build-logic/src/main/kotlin/org/terasology/gradology/exec.kt
Line 16 in 984d9e9
—but that single-player MR game seemed content with only a quarter of that (768M).
Places to adjust this:
DEFAULT_MAX_HEAP_SIZE
@Option
to set MaxDirectMemorySize, provide a defaultConsiderations:
Why did we set
DEFAULT_MAX_HEAP_SIZE
so high? (I think that change was within the last year or two.)The text was updated successfully, but these errors were encountered: