I have a game that operates on large 2d arrays for some procedural generation. Most of the game's logic is written in Lua, which I've optimized a lot, but there are some bottlenecks I might move into C.
As far as I can tell, the best way to bridge between the two is going to be registering a Lua class with pd->lua->registerClass
that defines a way to set/get data from a 2d array, something like this:
typedef {
int major;
int minor;
short **grid;
} Grid;
static int new_grid(lua_State *L) {
int major = pd->lua->getArgInt(1);
int minor = pd->lua->getArgInt(2);
Grid *grid = pd->system->realloc(NULL, sizeof(Grid));
grid->major = major;
grid->minor = minor;
short i;
short **array = pd->system->realloc(NULL, major * sizeof(short *));
array[0] = pd->system->realloc(NULL, major * minor * sizeof(short));
for (i = 1; i < major; i++) {
array[i] = array[0] + i * minor;
}
grid->data = array;
pd->lua->pushObject(grid, "c_Grid", 0);
return 1;
}
// garbage collect, :set() and :get() methods, etc.
static int operateOnCGrid(lua_State *L) {
Grid *grid = pd->lua->getArgObject(1, "c_Grid", NULL);
// do something with the Grid
}
pd->lua->registerClass("c_Grid", GridLib, NULL, 0, NULL);
pd->lua->registerFunction(operateOnCGrid, "operateOnCGrid", NULL);
Then, to prepare a 2d table in Lua for operations in C, I'd need to make an instance of the class to pass into an exposed function:
local cgrid = c_Grid.new(height, width)
for row = 1, height do
for col = 1, width do
cgrid:set(row-1, col-1, someValue)
end
end
operateOnCGrid(cgrid)
I wanted to confirm my understanding is correct, and that there's no more performant way to approach this. Right now I'm working with a 40x40 grid, and it's very slow to perform 1600 copies every time I pass the grid from C to Lua or vise versa.
I can avoid the repeated cost of performing this copy in/out by using a c_Grid
rather than a default table in my Lua code, but then I incur the overhead of C FFI every time I perform an array index/etc, which could be pretty often. From a quick profile, setting a value in a 2d Lua table is about 10x faster than invoking a method on a class registered from C to do the same thing.
It seems like the answer might just be profiling what the breaking points are for each approach and figure out the most performant way to combine them.