ondras / rot.js

ROguelike Toolkit in JavaScript. Cool dungeon-related stuff, interactive manual, documentation, tests!
https://ondras.github.io/rot.js/hp/
BSD 3-Clause "New" or "Revised" License
2.33k stars 254 forks source link

Possible ROT.Display._data memory leak? #80

Closed seiyria closed 8 years ago

seiyria commented 8 years ago

Hi!

I've been using ROT for a while, and for my particular game it seems I've run into some memory leaks. I definitely have some of my own at the moment, but internally ROT seems to be eating a ton of memory.

You can find my project here live if you want to profile it, and here is the code.

I've asked some folks to take a look at it and it was suggested to me that ROT.Display._data keeps increasing in size, but personally I've not made heads or tails of heap snapshots.

The way the game works is that a dungeon is generated, you go through it, die, and then the game automatically regenerates and spawns a new dungeon. I'm not sure if this is causing something internal to eat up a bunch of space. I could be completely wrong, but I'd rather get verification if possible of where the problem is.

Thanks in advance!

ondras commented 8 years ago

Hi @seiyria,

I am no memory profiling guru, but the Chrome memory tool seems to show a constant memory usage -- no leaks as time passes by. Can you elaborate on how do you measure your leaks?

ROT.Display._data is a hashmap used to store/cache all drawn cells, so its size directly corresponds to that display's dimensions. For a display of MxN, _data shall have at most MxN items. You can easily measure that variable's size by dumping Object.keys(display._data).length. This number shall be +- constant. Also, every time you do Display::clear(), the _data member is completely emptied.

How many instances of ROT.Display are you using? Are you creating more of them at runtime, or just those 4 created initially?

seiyria commented 8 years ago

I'm not either, which makes this difficult.

The problem is that the game runs out of memory after ... well, the time varies. Eventually, in chrome, the tab just goes white and stops rendering anything. Note that I am also using angular, but this has happened whether or not angular was present.

For mreasuring, I use the profiler tool to measure the heap allocations over time. I think that when specific entries don't get fully grayed out, they're not GC'd. However, I'm not sure why. I'm also not entirely sure if this is in ROT, but I wanted to see if you knew of or could think of anything that could narrow this down. Also, the heap profiles are annoyingly difficult to understand :(

Good to know that it does clear itself when I do display.clear... I do that rather frequently, so I don't know why this is even happening.

I'm only using one ROT.Display, actually, and splitting it into 4 sections (the number of sections depends on the number of characters - it could be anywhere from 1 to 4).

seiyria commented 8 years ago

Good news, I'm pretty sure it was just Chrome and hardware acceleration breaking. I'm testing it now. It's likely not ROT as I've been running this in firefox with no noticeable problems. Sorry about the bother!

jboyle commented 8 years ago

So I'm also running into this issue, and I'm not sure why this bug has been closed.

If you clear the display often, rot.js has a memory leak in chrome when running with hardware acceleration. On my machine, the memory usage increases steadily for 15 minutes, and then the browser tab crashes entirely.

This issue is entirely caused by Chrome - but hardware acceleration is enabled by default in the latest version, and there are no work arounds short of asking users to manually turn it off and restart their browser.

ondras commented 8 years ago

@jboyle would you mind providing a sample (jsfiddle or similar)? The issue is closed because I was unable to find any particular fix or code bug that would be the source/solution for this problem. As far as I can tell, rot.js itself is not leaking anything (evidence by other browsers) and fixing a browser-specific bug might be close to imposible from within the JS itself.

jboyle commented 8 years ago

Here's a basic jsfiddle showing the issue: https://jsfiddle.net/u43phtxy/14/

You can see the memory increasing in the Chrome Task Manager.

This goes slower than my project but memory increases steadily.

Not sure if there's anything you can really do about it other than letting people know it exists. I'm making a realtime game with scrolling environments, which requires a lot of refreshes - so ROT.js might not be the right framework for my project. But if I'd known this early on I could have saved myself some headaches.

FYI - the framework is awesome. Thanks for providing it!

ondras commented 8 years ago

I cannot really reproduce this. Just tried on Chrome 53, using the "Record allocation timeline" devtool profiler. The memory usage is almost constant, showing tiny variations during those scheduled repaints. Nothing that would look like a leak at all.

I agree that the memory amount in the Chrome Task Manager is going slowly up, but that can be caused by many other things (probably also including your OS's memory management) -- and it is almost certainly out of my reach.

Maybe the Chrome Devtools are periodically generating canvas snapshots for later inspection? I really have no idea.