Return to “Technical”

Post

Garbage Collection (GC)

#1
Hi, so I searched for the title, and found nothing, so if this needs merging anywhere, go right ahead :)

So, My Time at Portia was successfully funded, and Alpha 3.0 is coming out next week. :yay:
/me winks to Dinosawer

Image

I was reviewing some bugs from Pathea's Forums and reviewing the output.txt log file and found these interesting nuggets.
It uses Unity, so that might help?

Code: Select all

Unloading 11 unused Assets to reduce memory usage. Loaded Objects now: 5983.
Total: 0.973503 ms (FindLiveObjects: 0.161755 ms CreateObjectMapping: 0.109367 ms MarkObjects: 0.584372 ms  DeleteObjects: 0.117468 ms)
and

Code: Select all

Unloading 33722 unused Assets to reduce memory usage. Loaded Objects now: 113007.
Total: 315.695862 ms (FindLiveObjects: 6.306307 ms CreateObjectMapping: 7.529600 ms MarkObjects: 197.540573 ms  DeleteObjects: 104.319115 ms)
Now, my question is, in relation to
JoshParnell wrote:
Fri Jun 09, 2017 10:23 am
Flatfingers wrote:
Tue Jun 06, 2017 1:15 am
One question: does this make LuaJIT garbage collection irrelevant? How does GC fit into the new model?
Re GC: it definitely makes a certain percentage of it irrelevant. The higher that percentage, the higher the perf. My goal is 100%, so that we can turn off the GC entirely. That's actually a reasonable goal I believe, considering that we've already established how much of a difference having the data live in C makes. I will (and have already to some extent) make it as easy as possible for people to define new datatypes that can live on the C side, so that scripts can still have their own helper data and such without unknowingly invoking GC.

But even if we don't manage to do away with it entirely, keeping most of the data out of the Lua side makes GC way faster. GC times are roughly proportional to total Lua-allocated memory, so with 90% of the memory being managed by C, 90% of the GC's work goes away. It will be good :)
Sorry for the long-winded prose, but thanks for getting this far :clap:
Can anyone explain in numbers what LT does with it's new GC?
With a rough comparison of LT and the information above, how does LT perform?
Like for example, the recent asteroid field?

Thanks for listening :ghost:
YAY PYTHON \o/

In Josh We Trust
-=326.3827=-
Post

Re: Garbage Collection (GC)

#2
FormalMoss wrote:
Fri Oct 13, 2017 1:24 am
Sorry for the long-winded prose, but thanks for getting this far :clap:
Can anyone explain in numbers what LT does with it's new GC?
With a rough comparison of LT and the information above, how does LT perform?
Like for example, the recent asteroid field?

Thanks for listening :ghost:

I don't really understand what's being asked here...especially the reference to other games and Unity and such. Are you asking how LT memory management compares to a full-GCd environment? Or specifically how it might compare to those numbers?

Some general information that may be relevant to the answer: CTypes memory is not GCd. It is not part of the memory that Lua owns. It is owned by engine-level memory pools. Part of what makes our current system so fast is this very fact -- that we keep as much memory as possible out of the hands of the GC and owned/managed exclusively by our own constructs. We have much better knowledge about when and where memory needs to be freed than Lua could ever hope to have. So, in terms of, for example, asteroids...there is no memory to GC. Asteroids are a CType. When you allocate an asteroid, you get a pointer that is backed by one of the engine's memory pools (it creates a memory pool for every CType that is instantiated, yielding optimal cache locality and faster allocation/freeing than malloc). That asteroid is added to part of a list of entities in a given system. If and when it is destroyed, it will be removed from that list and the memory will be freed. None of this requires GC invocation and none of this will approach even the hundreds of microseconds range.

Part of what I implemented in this last batch of changes (mentioned only briefly in one of those bullet points) is refcounting for CTypes, which means the memory could be managed automatically using refcounting by CTypes (note that this is very different from being part of Lua's GCd memory, and vastly more efficient). This is for entities where the lifetime is not so easy to reason about.

In terms of those numbers, it's very hard to say. Lua is an incremental GC -- it doesn't just do a full pass. From the log, that GC looks to be doing a full pass all at once. But I don't know for sure. Maybe that print statement is happening at the end of a collection that occurred over many frames. Lua's incremental GC should, in general, take less than 1ms when it's running -- and it doesn't run very often, because we don't keep much memory in Lua. I'll probably be able to talk more precisely about numbers and timings when Adam finishes his work on memory profiling utilities. We were pretty blind to real-time GC behavior until this week, when he implemented the memory graph and a few other tools to keep an eye on GC.

That second snippet is disturbing and hopefully is just a final cleanup pass at application exit (which is, in itself, unnecessary...). If that's happening during the game...yikes! Again, though, it might be over many frames...I don't know. But nothing we do with memory should ever come close to 300ms. 3ms would be a really bad GC time for us IMO. I hope to always keep GC overhead as far below 1ms as possible. Some of this weeks work will help us achieve that, since it's much easier to target problematic areas now.
“Whether you think you can, or you think you can't--you're right.” ~ Henry Ford
Post

Re: Garbage Collection (GC)

#5
Silverware wrote:
Sat Oct 14, 2017 2:36 pm
Do what ever you can to disable the default GC and replace it with a better system.
There are few/nil languages that have good default GC's.

Implying that there exists such thing as a good GC :V Do point me in the right direction.... :ghost: :ghost:

JFSOCC wrote:
Sun Oct 15, 2017 11:15 am
One day I will take some NZT-48 and I'll suddenly understand more than just the gist of this.

:clap: Wooo for all things with limit in the title! :clap:
“Whether you think you can, or you think you can't--you're right.” ~ Henry Ford
Post

Re: Garbage Collection (GC)

#6
JoshParnell wrote:
Mon Oct 16, 2017 9:34 am
Silverware wrote:
Sat Oct 14, 2017 2:36 pm
Do what ever you can to disable the default GC and replace it with a better system.
There are few/nil languages that have good default GC's.
Implying that there exists such thing as a good GC :V Do point me in the right direction.... :ghost: :ghost:
Ever played with Javascript in V8? (eg Chrome or Node.js)
Not perfect, but it does a damn good job at handling my... excessive, memory usage preferences. :3
Goatbot reloads every single file, every time I reload him, and he can handle massive numbers of reloads without expanding his memory profile. I've had cases of him running for months at a time.
°˖◝(ಠ‸ಠ)◜˖°
Toba - A Development Dump
Post

Re: Garbage Collection (GC)

#7
Silverware wrote:
Mon Oct 16, 2017 2:02 pm
Ever played with Javascript in V8? (eg Chrome or Node.js)
Not perfect, but it does a damn good job at handling my... excessive, memory usage preferences. :3
Goatbot reloads every single file, every time I reload him, and he can handle massive numbers of reloads without expanding his memory profile. I've had cases of him running for months at a time.
I haven't, but I should. I imagine V8 must be one of the best out there.

The scenario you mention is actually a pretty good use case for tracing GC I think, though. If you have loads of garbage that is going to be generated all-at-once but infrequently, tracing can outperform refcounting, since references are extra overhead for keeping track of stuff which is mostly going to be destroyed. I definitely don't worry about it, for example, in the procedural algorithms where engine-level mesh operations and the like are going to take up the vast majority of the time and we can also get away with being 'excessive' :P The place where it hurts is in high-frequency temporary allocations, especially if the compiler doesn't do enough work to figure out that the allocation could be sunk into a local scope rather than lazily (in both senses of the word..) dealt with by tracing. If the latter happens, then you have needless garbage building up every frame until GC kicks in, so very innocuous-looking code can go on to completely wreck performance (something that we can now see very acutely thanks to Adam's memory profiler... :shock:)

Thankfully LuaJIT does a pretty darn good job of reasoning about that stuff -- it will make most local variable allocations disappear completely with its 'allocation sinking' optimizing pass if it can put a bound on the lifetime of them. But there are situations (that occur frequently) where that bound is too difficult to reason about (one such situation is calling into the engine's C API using a local variable), in which case GC overhead is incurred (to be fair, native calls will be a problem for any auto memory management, regardless of tracing or refcounted).

I just think mark & sweep needs to die. Maybe someday I'll come to the same enlightenment as those who employ it :V

Is there any way that 'excessive memory usage preference' could be causing me to lose to goatbot at blackjack all the time? :ghost:

PS ~ Speaking of things that need to die, love that avatar.... x_x
“Whether you think you can, or you think you can't--you're right.” ~ Henry Ford
Post

Re: Garbage Collection (GC)

#8
Na, Goatbot's Blackjack was surprisingly mild. It's more the reloading of every single module in him when I reload, even if there were no on-disk changes for them.


Anyway Wikipedia states two fun facts about V8;
First: That it compiles from JS to Native Machine Code.
Second: That it's garbage collector is a generational incremental collector.

The second point being the one that'll interest you.
https://en.wikipedia.org/wiki/Chrome_V8

I have no idea how that is implemented. But I can tell you that it works like a charm.
Especially seeing as I am in the habit of using let, which is basically var done properly, respecting context and everything.


And as for the avatar? Well, it's the best thing since Oatbot.
°˖◝(ಠ‸ಠ)◜˖°
Toba - A Development Dump

Online Now

Users browsing this forum: No registered users and 1 guest

cron