How to add finalizers on light userdata -- for instant node creation #28
Replies: 2 comments
-
This sounds like premature optimization. I don't know how subnode
"creation" happens, but if there's memory to be alloc'ed, you may as
well have Lua do it as a userdata.
The whole point of Lua light userdata is access to managed memory
outside of Lua (C-land structs and such). Lifecycle methods with light
userdata just doesn't exist as far as I know.
If you want to pre-allocate subnodes in a parent, they'll be collected
with the parent. Sure, they won't be collected right away in your
example, but they'll still be collected when the parent is. That said, I
still don't see why you wouldn't just use a full userdata for subnodes.
This is just from my Lua perspective. I am not keeping up with
lua-yottadb development.
|
Beta Was this translation helpful? Give feedback.
-
Oops. This will probably make more sense now that I've released the matching blog article on making lua-yottadb fast. I have linked it now. I like your idea @orbitalquark, that subnodes will be collected when the parent is eventually collected. But I fear that your solution will not work because, in this case, the parent itself will never be collected since the preallocated subnodes within it reference it -- they must do so until the subnodes themselves are called by a finalizer. But since Thanks for your reply. I have added your (very sensible) objection of premature optimization to the write-up. |
Beta Was this translation helpful? Give feedback.
-
This is the place to submit your ideas on the "Gauntlet Challenge" that I issued in this article on the process of making lua-yottadb fast.
Instant subnode creation is possible if
light userdata
were used for it. However, these nodes could never be freed since__gc
finalizer methods do not work onlight userdata
in Lua. Can anyone think of a workaround?Consider a Lua object for database node
demographics
. Subnodes can be accessed using dot notation:demographics.country.person
. Currently, subnodes have the overhead of allocating a fulluserdata
. But Lua has a cheaper type called alight userdata
: which is nothing more than a C pointer, and free to create. If we were to pre-allocate space for several subnodes within the parent node'suserdata
, child nodes could simply point into it, making subnodes virtually instant.But there's a gotcha. Since a
light userdata
object has no storage, Lua doesn't know what type of data it is, and therefore what metatable (i.e. object methods) to associate with it. So there's a single global metatable for alllight userdata
objects. No matter: we can still hook the global metatable, and then double-check ourselves that it points to a subnode before running node class methods on it. Should work fine.Subnode creation time in lua-yottadb v2.1 is already as fast as creating a full
userdata
, but I'm anticipating this improvement will increase that speed to at least 4x as fast. This will also keep all allocated memory together in one place: better for CPU caching.This hack would actually work … except for one problem: it can't collect garbage. Tragically, Lua ignores the
__gc
method onlight userdata
. This means we'll never be able to remove thelight userdata's
reference to its root node. Which creates a memory leak. Here's an example to explain:First the
root
node is created; thensubnode
referencesroot
; then Lua assignssubnode
tox
so thatx
now referencessubnode
. Finally,x
is deleted. The problem is that whenx
is garbage-collected, Lua does not collect the light userdatasubnode
(which is still referencing root). So root is not collected, leading to a memory leak.Can anyone see a solution to this puzzle? I'm throwing down the gauntlet. Find a way to work around Lua's lack of garbage collection on light userdata.
Beta Was this translation helpful? Give feedback.
All reactions