Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 28 Feb 2011
Offline Last Active Today, 05:52 AM

Topics I've Started

Lua, collecting garbage on exception?

23 December 2015 - 03:06 AM



In our project we use Lua as application code which calls into modules implemented either in Lua or in a lower level language. This works very well for us, but throughout the project we have had some issues dealing with Lua errors robustly. Because our Lua scripts are application-level logic, they routinely manipulate userdata provided by the lower-level modules; many of these structures hold system resources and need to be quickly finalized after we are done with them. We have close() functions in our code to this end, but, of course, if a Lua error is thrown, this doesn't happen until the garbage collector decides to run (we have correct __gc metamethods) which may be never since the default GC strategy is to only collect when a certain amount of memory is used. This is, naturally, unacceptable.


We don't abort on error because our Lua scripts run an event loop; we catch Lua exception at the callback boundary, log it, and usually resume the loop afterwards; the program is terminated only in the case of a catastrophic error, or if something goes wrong before starting the event loop (e.g. parsing a config file, ...).


So a few weeks ago I had a seemingly simple but apparently effective idea: override pcall with an implementation which, in case of an error, triggers the garbage collector; as far as I can tell this provides very strong guarantees about the finalization of resources acquired within a failed Lua chunk; since we don't use globals, the only accidental way for these resources to escape finalization is for them to be referenced in upvalues or table/userdata parameters of that chunk before it fails, which is easy to, like, not do. Just keep them in locals and either return them as you would normally, or lift them outside the chunk through its upvalues at the very end.


The problem I can't seem to find any references to this pattern; are there any downsides to this? Because as far as I can tell this is a free lunch:


 - trivial to implement: override pcall, add lua_gc() calls on error. done

 - ensures that all failed resources are immediately finalized in case of failure

 - has zero overhead (and if no error occurs, our normal code path does the cleanup by itself)


Any thoughts? Any obvious defect I overlooked? Has anyone seen and/or done this before, and did it work for you?




EDIT: actually this isn't quite true; I did find exactly 2 references to this pattern, one on the Lua website (supposedly the vanilla Lua interpreter does the same thing in interactive mode when user input fails for some reason, but I can't find the code that does it in the Lua 5.3 distribution so maybe it doesn't do it anymore) and here: http://lua-users.org/lists/lua-l/2009-02/msg00191.html but it doesn't go into a lot of detail.

LaTeX in journals?

19 February 2015 - 03:21 AM

The MathJax headers don't seem to be present in the developer journal pages, as a result the new LaTeX tags that work on the forum can't be used:

\( <inline LaTeX> \)
\[ <formula LaTeX> \]

Could MathJax be enabled for the developer journals section of the site? Thanks!

AntTweakBar for C#

22 October 2013 - 03:04 AM

Hello, does anyone know of, or has anyone written a - free - wrapper for the AntTweakBar GUI library for C#? Just asking before I start writing my own, can't find one on the internet at all (which is surprising, I'd imagine someone somewhere would have already created one). The API looks straightforward enough to port, but I'd really hate to reinvent the wheel.



Reputation bug?

26 July 2013 - 08:36 PM

Aren't new members supposed to start at 101 points? This recent member (and possibly others) appears to have started at 1 reputation point (making his reputation appear as "bad" despite the fact that he was never downvoted). Perhaps this should be addressed (and see if there is an underlying bug at work)?


I just noticed it so heads-up to the staff smile.png

Memory allocation for low-level library

04 July 2013 - 08:58 AM


I have a rather low-level C library I'm working hard on, and I've finally gotten to overhauling the memory manager. For now I've been using malloc/free as usual, but because many of my structures are nested and recursively allocated, this leads to a lot of cache misses as all my stuff is scattered all over the address space, subject to the host application's memory patterns. Furthermore, I also need additional features (virtual page locking, notably) which requires an additional kernel call per virtual allocation, and tends to interfere with the host application (page straddling, that kind of thing).


I've been looking over various memory allocation techniques, trying to find one that would best fit my library's needs. What I've established is that by design, blocks allocated by my library are either very short-lived, or very long-lived, and are allocated/deallocated in a roughly stack-like fashion. Furthermore, those blocks are typically small (there are many "small" structures of 16-32 bytes, and some "medium" structures around 64-512 bytes, and definitely no massive blocks). Finally, applications using the library are unlikely to accumulate many memory blocks at once, they will instead allocate a few, deallocate them, allocate them again, and so on (or just reuse them directly). There is also no reallocation going on: the library knows how much it needs and never has to resize any blocks it allocates. I've also worked extremely hard to ensure the library functions are using constant memory with respect to user input, so no worries there, all allocations are controlled with well-defined size limits.


Finally, I'd like to allow the option of users providing their own custom allocator if they so desire, so my default, optimally tuned allocator would need to follow a proper interface (likely simply a memory allocation function (unaligned and aligned flavours) and a deallocation function). That's probably not too hard, though.


I've reduced my choices to two allocation strategies:

1. static/dynamic memory pool allocation hybrid.

2. region-based allocation.


The first choice would involve first using a static, small, high-performance pool to store requested blocks, and falling back to a generic dynamic pool strategy whenever the library runs out of space. This option is very attractive to me, because most applications would only ever use the static pool, leading to optimum cache coherency, pretty low overhead, and it also lets the library do all the setup work at the start and never worry about it after. The few more demanding applications won't keel over, either, but will simply revert to the less efficient dynamic pool allocator.


The second option is nice as it would fit the memory usage pattern of the library better, but I think region-based allocators need additional information like distinguishing allocating a region and allocating a block inside a given region (imposing additional work on the library's implementation and making it hard to interop with other allocators) and it wouldn't work too well with any "deep copy" functions which can potentially increase the size of a region by modifying the size of a nested structure, since they hold pointers to more structures, not the structures themselves. Overall it sounds like a logistical nightmare.


So I am leaning towards the first option, but I am not sure if this "cache-based" allocation strategy has been done before and if it is really beneficial. Of course I don't want something ridiculously complicated either, which is why I'd prefer a simple, "all in one" solution. I really just want something elegant, efficient, and tailored to my library, not a general-purpose malloc-style infrastructure.


You may assume the target processors for this allocator are generic consumer-grade CPU's. The library will also have embedded hardware support but obviously that will have a different codepath).


What do you guys think?


Thanks smile.png