lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

----- Original Message -----
From: David Given
Date: 2/6/2012 6:44 AM
Mike Pall wrote:
Reference counting (RC) has plenty of practical problems. One key
aspect is that the impact is hard to measure, since the overhead
is spread out all over the code. Some issues, like excessive
number of writes, cache pollution, unbounded latency vs. delayed
free, etc. can be solved with more complex variants of RC.
In an earlier life I worked on an object-oriented operating system where
all objects were reference counted.

Never, never again.

Not *only* does it have the problems described above, it's also
incredibly brittle and easy to break. Forgetting to take a reference or
drop a reference can lead to obscure and hard-to-find bugs. And it makes
the code verbose and difficult to read. *And* since dropping a reference
can conceivably lead to the object being destroyed then and there, if it
was the last reference, it means you have to be really careful when
references get dropped.
For the games we developed with the reference counting system in LuaPlus (or for regular Lua, LuaRC), it solved a variety of woes _automatically_.

I've discussed the performance benefits for more memory intensive scripts on the list before. I can look them up, if you care.

You refer to issues where the object is destroyed then and there. Well, having deterministic finalization is really cool. If I had a Lua object referring to an open file, I know that the file object's __gc method is going to be called as soon as the object falls out of scope. The file won't stay open until some point in the future when the garbage collector kicks in, leading to unpredictable and hard to find bugs! Deterministic finalization _prevents_ these bugs from occurring.

I ran into a few problems with reference counting within Lua.

1) Cycles cannot be detected, and the full Lua garbage collect has to be run. In my code, there were no cycles, so we never ran the Lua garbage collector during 'real-time' gameplay.

2) Reference counting has a cost, and it slows down the VM across the board. This was not really measurable for us, though. Running the Lua garbage collector always resulted in **major** cache misses as it visited objects spread across the memory spectrum. Incrementing and decrementing a reference count may possibly result in a cache miss, but it probably doesn't, given that the object was generally just accessed and in the cache anyway.

3) I never fully implemented supported for weak objects. I just let the garbage collector do its thing.

A generational collector may be as effective as a reference counting system, but I doubt it. I hope to be proven wrong, though. In my experience, the biggest issue I have dealt with in games using Lua is with the time to garbage collect objects. Lua 5.1's incremental collector is a step forward, but you still run across blog posts where game developers hacked the GC to abort within a certain period of time. Or they force delayed garbage collection until a certain point. The list goes on.