[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: A proposal for faster userdata type checking
- From: Chris <coderight@...>
- Date: Thu, 28 Feb 2008 10:57:32 -0500
The current luaL_newmetatable/luaL_checkudata auxiliary functions are
fine but luaL_checkudata adds a significant amount of overhead when
making heavy use of calls that need to check userdata types (which is
very important when creating "safe" APIs). I have attached a small
extension patch that adds lua_tomuserdata() and luaL_checkmudata() to
the core which gives the application quicker access to the metatable
pointer. From the developer perspective nothing changes unless they
want to use the new mechanism.
Example usage (simplified):
void *myusertype_meta;
int create_myusertype(lua_State *L) {
...
luaL_newmetatable(L, "myusertype");
/* cache the metatable pointer locally */
myusertype_meta = lua_topointer(L, -1);
...
}
int some_lua_function(lua_State *L) {
myusertype *ud = luaL_checkmutype(L, 1, "myusertype", myusertype_meta);
...
}
I see about a 30+% increase in general application speed plus the
normal API still works as usual of course. What do you think?
CR
diff -ru lua-5.1.3.orig/src/lapi.c lua-5.1.3/src/lapi.c
--- lua-5.1.3.orig/src/lapi.c 2008-01-03 10:20:39.000000000 -0500
+++ lua-5.1.3/src/lapi.c 2008-02-28 10:44:13.429884590 -0500
@@ -393,6 +393,18 @@
}
+LUA_API void *lua_tomuserdata (lua_State *L, int idx, const void *meta) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TUSERDATA:
+ if (uvalue(o)->metatable == meta) return (rawuvalue(o) + 1);
+ return NULL;
+ case LUA_TLIGHTUSERDATA: return pvalue(o);
+ default: return NULL;
+ }
+}
+
+
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
StkId o = index2adr(L, idx);
return (!ttisthread(o)) ? NULL : thvalue(o);
diff -ru lua-5.1.3.orig/src/lauxlib.c lua-5.1.3/src/lauxlib.c
--- lua-5.1.3.orig/src/lauxlib.c 2008-01-21 08:20:51.000000000 -0500
+++ lua-5.1.3/src/lauxlib.c 2008-02-28 10:44:30.923498327 -0500
@@ -137,6 +137,14 @@
}
+LUALIB_API void *luaL_checkmudata (lua_State *L, int ud, const char *tname, const void* meta) {
+ void *p = lua_tomuserdata(L, ud, meta);
+ if (p != NULL) return p;
+ luaL_typerror(L, ud, tname); /* else error */
+ return NULL; /* to avoid warnings */
+}
+
+
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
if (!lua_checkstack(L, space))
luaL_error(L, "stack overflow (%s)", mes);