lua-users home
lua-l archive

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


On Tue, Sep 10, 2013 at 02:58:31PM +0900, Miles Bader wrote:
> William Ahern <william@25thandClement.com> writes:
> >> It never occurred to me to try integer keys (or rawgeti), but as that
> >> presents additional issues (e.g., one must come up with a system to
> >> assign small-integer keys without conflicts), and has no particular
> >> library support (luaL_checkudata etc), it seems like I may as well
> >> just use upvalues when possible (and upvalues of course have the
> >> advantage of being a local namespace, with no namespace conflict
> >> issues).
> >
> > If you use lightuserdata there's no namespacing conflict, assuming a flat
> > process address space. Just take the address of a function, or if casting
> > function pointers to void pointers is distasteful, define a static const
> > variable and use its address.
> 
> Hmm, then you presumably don't get the same speed advantage as small
> integers, right?  I guess hashing a lightuserdata might be faster than
> hashing a string, although I dunno how much for short strings...
> 

According to this test code for Lua 5.2, lightuserdata is actually faster.
Upvalue loads are significantly faster, but the absolute costs are so
incredibly miniscule as to be entirely unimportant.

Here are the values for my test run:

lua_rawgeti * 16777216: 0.538696
lua_rawgetp * 16777216: 0.47124
lua_pushvalue * 16777216: 0.278008
lua_rawgeti * 16777216: 0.536791
lua_rawgetp * 16777216: 0.472952
lua_pushvalue * 16777216: 0.278359
lua_rawgeti * 16777216: 0.534699
lua_rawgetp * 16777216: 0.471725
lua_pushvalue * 16777216: 0.278197

And the code:

#include <stdio.h>
#include <time.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#define MAX  1<<24
#define NUP  8

static int none(lua_State *L) {
	clock_t start = clock();

	for (int i = 0; i < MAX; i++) {
		lua_pushvalue(L, lua_upvalueindex(i % NUP));
		lua_pop(L, 1);
	}

	printf("lua_pushvalue * %d: %g\n", MAX, (double)(clock() - start) / CLOCKS_PER_SEC );

	return 0;
}

int main(void) {
	lua_State *L = luaL_newstate();
	clock_t start;

	for (int i = 0; i < 3; i++) {
		start = clock();

		for (int i = 0; i < MAX; i++) {
			lua_rawgeti(L, LUA_REGISTRYINDEX, i);
			lua_pop(L, 1);
		}

		printf("lua_rawgeti * %d: %g\n", MAX, (double)(clock() - start) / CLOCKS_PER_SEC );

		start = clock();
	
		for (int i = 0; i < MAX; i++) {
			lua_rawgetp(L, LUA_REGISTRYINDEX, (void *)((char *)L + i));
			lua_pop(L, 1);
		}

		printf("lua_rawgetp * %d: %g\n", MAX, (double)(clock() - start) / CLOCKS_PER_SEC );

		for (int i = 0; i < NUP; i++) {
			lua_pushnumber(L, i);
		}
		lua_pushcclosure(L, &none, NUP);
		lua_call(L, 0, 0);

		/* grow registery */
		for (int i = 0; i < 256; i++) {
			lua_pushnumber(L, 0xd0d0caca);
			luaL_ref(L, LUA_REGISTRYINDEX);
		}
	}

	return 0;
} /* main() */