lua-users home
lua-l archive

Re: ways to avoid (or speed up) luaL_checkudata() in LuaJIT2?

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


> > the problem is that [luaL_checkudata] this function actually needs to
> > create a new string in order to do the user data name check at all.
> 
> If that is a problem for your application, just write your own
> luaL_checkudata and luaL_newmetatable. You can for instance use void*
> instead of strings and use a static address in your library.
To test the performance of this approach, I've added the code below to
my lcomplex library and ran a simple Mandelbrot test. This tests creates
lots of temporary complex numbers that need to be checked at each step.
Here are the timings: the new scheme takes 70% of the original tinme.
Original scheme -- using strings as keys
0.780u 0.024s 0:00.80 100.0%	0+0k 0+104io 0pf+0w
New scheme -- using light udata as keys
0.540u 0.020s 0:00.55 101.8%	0+0k 0+104io 0pf+0w
Unsafe scheme -- no checking of udata
0.436u 0.012s 0:00.44 100.0%	0+0k 0+0io 0pf+0w
The unsafe scheme uses just this:
#define luaL_checkudata(L,i,s)	lua_touserdata(L,i)
Here is the code, which was based directly on the code in lauxlib.c.
For production, the my_* functions should probably receive the pointer
&mykey, instead of using it directly.
/* udata.c. Include it after lauxlib.h. */
static int mykey=0;
static int my_newmetatable (lua_State *L) {
 lua_pushlightuserdata(L,&mykey);
 lua_rawget(L, LUA_REGISTRYINDEX);
 if (!lua_isnil(L, -1)) /* name already in use? */
 return 0; /* leave previous value on top, but return 0 */
 lua_pop(L, 1);
 lua_newtable(L); /* create metatable */
 lua_pushlightuserdata(L,&mykey);
 lua_pushvalue(L, -2);
 lua_rawset(L, LUA_REGISTRYINDEX);
 return 1;
}
static void my_getmetatable (lua_State *L) {
 lua_pushlightuserdata(L,&mykey);
 lua_rawget(L, LUA_REGISTRYINDEX);
}
static void *my_checkudata (lua_State *L, int ud, const char *tname) {
 void *p = lua_touserdata(L, ud);
 if (p != NULL) { /* value is a userdata? */
 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
 lua_pushlightuserdata(L,&mykey);
 lua_rawget(L, LUA_REGISTRYINDEX); /* get correct metatable */
 if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
 lua_pop(L, 2); /* remove both metatables */
 return p;
 }
 }
 }
 luaL_typerror(L, ud, tname); /* else error */
 return NULL; /* to avoid warnings */
}
#undef	luaL_getmetatable
#define luaL_getmetatable(L,s)	my_getmetatable(L)
#define luaL_newmetatable(L,s)	my_newmetatable(L)
#define luaL_checkudata(L,i,s)	my_checkudata(L,i,s)

AltStyle によって変換されたページ (->オリジナル) /