- Size of coroutine: 400 bytes
- Each VM requires ~10k physical, 128k virtual memory
- JIT disabled on iOS because Apple doesn't support run time code generation
- JIT disabled on Windows 8 for ARM for the same reason
- LuaJIT interpreter(no JIT) is ~3x faster than standard Lua
- LuaJIT with JIT enabled is ~20x faster than standard Lua
- Lua C API prevents JIT compilation
- LuaJIT FFI is much faster if compiled, but if not compiled(like on iOS), it is slower than the Lua C API
- LuaJIT FFI cannot be safetly sandboxed, do not use for user scripts(Mike Pall recommends process isolation)
- LuaJIT GC considerations by Mike Pall
- 1 to 2GB/ memory limit(depending on OS and x86/64) for current LuaJIT, extended to 2-4GB whenever the new GC arrives , but you wouldn't ever want to allocate that much memory
- All LuaJIT allocations must be within first 2GB of address space
- LuaJIT 3.0 will have a brand new GC, optimized for real time applications
- Tracing compiler discussion with Mike Pall(LuaJIT) and Brenden Eich(Javascript), worth reading the entire thing
- Design of LuaJIT: optimization, register allocation
- Lua 5.2 __gc metamethod not support for tables yet in LuaJIT, can use newproxy, an undocumented Lua function, to work around this
- LuaJIT bytecode 40% smaller than standard Lua
Showing posts with label Lua. Show all posts
Showing posts with label Lua. Show all posts
LuaJIT info & links
LuaJIT
Components system + Flow Graph
Like lots of other games, my game uses a component system.
This system is designed to allow for improved cache usage and easy parallelization.
It is loosely based on this article published by Insomniacs.
For cache friendly behavior all components of a given type live in contiguous memory, and are all updated together.
To specify attributes for components I have a Lua file, which for each component type indicates, among other things, how they should update(parallel, serial), and which other component types they depend on.
I use TBB Flow Graph to express dependencies, any component that has a dependency on another being updated prior to it, just lists that component as a dependency in the Lua file.
For instance this is the declaration of my Occlusion Rasterizer component in Lua.
reg("occlusion_rasterizer", no_inteface, TM.MULTI, 0.0, 3, {"commands"})
The parameters in order are:
name - name in C++, this matches them up
interface - specifies which interface, if any, the component implements, if Occlusion Rasterizer had implemented an interface this would be the name of that component. This allows for things like finding all components that implement a given interface.
parallel - either SINGLE or MULTI, SINGLE means each component of this type is updated sequencially, MULTI means they are all updated in parallel
time delay - how long between updates to this type, so if you want a given type to only update 4 times per second make this value 0.25 etc
count - how many components to reserve, this allocates a contiguous block of memory. It will grow as needed, but this allows for the equivalent of a vector.reserve()
dependencies - list of any components that must update prior to this component, TBB flow graph guarantees they will finish updating prior to this component updating. Occlusion Rasterizer depends on a command list being generated, so it lists "commands" as a dependency.
Each component type derives from a base component type in C++, currently this adds 12 bytes of overhead to each instance in 32 bit builds, and 16 bytes in 64 bit builds.
The base component contains this:
vtable ptr - 4/8 bytes. Removing this is possible but makes the system somewhat clumsier to use.
chain index - 4 bytes, which chain it is on, chains are a series of components
type - 2 bytes, each component type has a unique ID
offset - 2 bytes, index into the pool containing components of its type
I've been pretty happy with this system, my components are small self contained little objects, they are cache friendly, and can be allocated and destroyed in large numbers. Adjusting dependencies as new types are added is also a very simple since no recompilation is needed, just a chance to a Lua script file.
A major advantage of component systems, which I think does not get stated clearly enough, is how much glue code they save you from writing. Having to create classical C++ game objects and populate them with appropriate member data, worry about all the fragile and arbitrary hierarchies, and then writing all the systems that control them is a huge amount of unnecessary code.
This system is designed to allow for improved cache usage and easy parallelization.
It is loosely based on this article published by Insomniacs.
For cache friendly behavior all components of a given type live in contiguous memory, and are all updated together.
To specify attributes for components I have a Lua file, which for each component type indicates, among other things, how they should update(parallel, serial), and which other component types they depend on.
I use TBB Flow Graph to express dependencies, any component that has a dependency on another being updated prior to it, just lists that component as a dependency in the Lua file.
For instance this is the declaration of my Occlusion Rasterizer component in Lua.
reg("occlusion_rasterizer", no_inteface, TM.MULTI, 0.0, 3, {"commands"})
The parameters in order are:
name - name in C++, this matches them up
interface - specifies which interface, if any, the component implements, if Occlusion Rasterizer had implemented an interface this would be the name of that component. This allows for things like finding all components that implement a given interface.
parallel - either SINGLE or MULTI, SINGLE means each component of this type is updated sequencially, MULTI means they are all updated in parallel
time delay - how long between updates to this type, so if you want a given type to only update 4 times per second make this value 0.25 etc
count - how many components to reserve, this allocates a contiguous block of memory. It will grow as needed, but this allows for the equivalent of a vector.reserve()
dependencies - list of any components that must update prior to this component, TBB flow graph guarantees they will finish updating prior to this component updating. Occlusion Rasterizer depends on a command list being generated, so it lists "commands" as a dependency.
Each component type derives from a base component type in C++, currently this adds 12 bytes of overhead to each instance in 32 bit builds, and 16 bytes in 64 bit builds.
The base component contains this:
vtable ptr - 4/8 bytes. Removing this is possible but makes the system somewhat clumsier to use.
chain index - 4 bytes, which chain it is on, chains are a series of components
type - 2 bytes, each component type has a unique ID
offset - 2 bytes, index into the pool containing components of its type
I've been pretty happy with this system, my components are small self contained little objects, they are cache friendly, and can be allocated and destroyed in large numbers. Adjusting dependencies as new types are added is also a very simple since no recompilation is needed, just a chance to a Lua script file.
A major advantage of component systems, which I think does not get stated clearly enough, is how much glue code they save you from writing. Having to create classical C++ game objects and populate them with appropriate member data, worry about all the fragile and arbitrary hierarchies, and then writing all the systems that control them is a huge amount of unnecessary code.
Lua needs
Lua is great, but it is missing a few things..
1. continue -- although Lua 5.2 adds goto, which does allow you to simulate this, but I don't see myself using goto..
2. no ++ or += etc. -- don't know why this isn't supported, shouldn't be too hard to add with custom pre-compiler
3. metaprogramming --Lua just doesn't have any good support for this, have to manipulate strings to accomplish anything
1. continue -- although Lua 5.2 adds goto, which does allow you to simulate this, but I don't see myself using goto..
2. no ++ or += etc. -- don't know why this isn't supported, shouldn't be too hard to add with custom pre-compiler
3. metaprogramming --Lua just doesn't have any good support for this, have to manipulate strings to accomplish anything
Lisp
Recently I've been teaching myself lisp-- so far it seems like a very creative language, which I like, as I view creativity as one of the most important skills for a programmer to have.
There are like a million different versions of lisp it seems and no single standard implementation.
And for whatever reason I decided to write yet another...
My lisp compiles to Lua, I figured that LuaJIT2 is the fastest dynamic language VM around, so targeting it should allow my Lisp implementation to perform better than most. I had no experience with Lisp prior to this, but I certainly learned lisp fairly well while writing a compiler for it-- also improved my Lua.
It is somewhat different from the lisp norm in that it does not use lists and cons cells, instead I use a Lua table in array form. No named arguments either, although you can fake them just as you would in Lua. I also use { to introduce raw Lua code, and } to return to Lisp.
Still have to implement most of the library functions that come with most lisp implementations, and I'm sure I'll have to fix a few bugs in the compiler yet, but it is working, including support for macros.
I also saw that the creator of Lisp, John McCarthy, died a few days ago:(
There are like a million different versions of lisp it seems and no single standard implementation.
And for whatever reason I decided to write yet another...
My lisp compiles to Lua, I figured that LuaJIT2 is the fastest dynamic language VM around, so targeting it should allow my Lisp implementation to perform better than most. I had no experience with Lisp prior to this, but I certainly learned lisp fairly well while writing a compiler for it-- also improved my Lua.
It is somewhat different from the lisp norm in that it does not use lists and cons cells, instead I use a Lua table in array form. No named arguments either, although you can fake them just as you would in Lua. I also use { to introduce raw Lua code, and } to return to Lisp.
Still have to implement most of the library functions that come with most lisp implementations, and I'm sure I'll have to fix a few bugs in the compiler yet, but it is working, including support for macros.
I also saw that the creator of Lisp, John McCarthy, died a few days ago:(
Subscribe to:
Posts (Atom)