[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: is it possible to make longjmp-free Lua?
- From: David Manura <dm.lua@...>
- Date: Sat, 1 Aug 2009 00:52:57 -0400
On Wed, Jul 29, 2009 at 5:34 AM, Juris Kalnins wrote:
> May I ask how big was your speedup?
> I just tried microbenchmark with lua_cpcall and the following:
> .... and got 0.15 vs 0.22 seconds on 1000000 calls on core2, and 40 vs 47
> seconds on mips. I was expecting something more spectacular...
About 1.3x (Linux/gcc3.4) to 6x (Cygwin/gcc3.4) speedup over
lua_cpcall depending on the compiler. See below.
=====
/* improved equivalent of lua_cpcall */
/* warning: assumes function pointers fit inside regular lightuserdata */
#include <lua.h>
#include <lauxlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
const int N = 10000000;
int cpcallproxy(lua_State * L) {
lua_CFunction f = (lua_CFunction)lua_touserdata(L, 1);
lua_remove(L, 1);
return f(L);
}
int myluacpcall(lua_State * L, lua_CFunction func,
int nargs, int nresults, int errfunc)
{
lua_pushvalue(L, 1); /* cpcallproxy */
lua_insert(L, -nargs-1);
lua_pushlightuserdata(L, (void*)func);
lua_insert(L, -nargs-1);
return lua_pcall(L, nargs+1, nresults, errfunc);
}
static int myluapushstringhelper(lua_State * L) {
lua_pushstring(L, (const char*)lua_touserdata(L, 1));
return 1;
}
int myluapushstring(lua_State * L, const char * s) {
lua_pushlightuserdata(L, (char*)s);
return myluacpcall(L, myluapushstringhelper, 1,1,0);
}
int test(lua_State * L) {
return 0;
}
int test2(lua_State * L) {
//luaL_error(L, "failed");
lua_pushnumber(L, lua_tonumber(L, 1) + strlen(lua_tostring(L,2)));
return 1;
}
static int init_helper(lua_State * L) {
lua_pushcfunction(L, cpcallproxy);
return lua_error(L);
}
int init(lua_State * L) {
int ret = lua_cpcall(L, init_helper, NULL);
if (ret == LUA_ERRRUN) ret = 0;
return ret;
}
void tests(lua_State * L) {
int i;
clock_t start, diff;
// test: lua_cpcall
start = clock();
for(i=0; i<N; i++) {
if (lua_cpcall(L, test, 0) != 0) {
printf("error:%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
printf("lua_cpcall: %f\n", ((double)(clock() - start)) / CLOCKS_PER_SEC);
// test: lua_pcall
start = clock();
for(i=0; i<N; i++) {
lua_pushvalue(L, 2);
if (lua_pcall(L, 0,0,0) != 0) {
printf("error:%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
printf("lua_pcall: %f\n", ((double)(clock() - start)) / CLOCKS_PER_SEC);
// test: lua_call
start = clock();
for(i=0; i<N; i++) {
lua_pushvalue(L, 2);
lua_call(L, 0,0);
}
printf("lua_call: %f\n", ((double)(clock() - start)) / CLOCKS_PER_SEC);
// test: myluacpcall
start = clock();
for(i=0; i<N; i++) {
if (myluacpcall(L, test, 0, 0, 0) != 0) {
printf("error:%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
printf("myluacpcall: %f\n", ((double)(clock() - start)) / CLOCKS_PER_SEC);
// test: myluacpcall2
start = clock();
for(i=0; i<N; i++) {
lua_pushnumber(L, 4);
if (myluapushstring(L, "test") != 0) {
printf("error:%s\n", lua_tostring(L, -1));
lua_pop(L, 2);
continue;
}
if (myluacpcall(L, test2, 2, 1, 0) != 0) {
printf("error:%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
//printf("%f\n", lua_tonumber(L, -1));
lua_pop(L, 1);
}
printf("myluacpcall2: %f\n", ((double)(clock() - start)) / CLOCKS_PER_SEC);
printf("---\n");
}
int main() {
int i;
lua_State * L = luaL_newstate();
if (L == NULL) return 1;
init(L);
// used by some tests
lua_pushcfunction(L, test);
for (i=0; i<3; i++) {
tests(L);
}
return 0;
}
=====
(gcc 3.4/cygwin)
$ gcc -O2 lt.c -llua
$ ./a.exe
lua_cpcall: 17.235000
lua_pcall: 2.296000
lua_call: 0.860000
myluacpcall: 2.906000
myluacpcall2: 10.078000
---
lua_cpcall: 17.547000
lua_pcall: 2.359000
lua_call: 0.860000
myluacpcall: 2.906000
myluacpcall2: 10.172000
---
lua_cpcall: 17.344000
lua_pcall: 2.281000
lua_call: 0.875000
myluacpcall: 2.844000
myluacpcall2: 10.093000
---
(gcc 3.4/cygwin-mingw)
$gcc -mno-cygwin lt.c -llua
$ ./a.exe
lua_cpcall: 6.922000
lua_pcall: 1.672000
lua_call: 1.047000
myluacpcall: 2.312000
myluacpcall2: 9.782000
---
lua_cpcall: 6.984000
lua_pcall: 1.484000
lua_call: 0.844000
myluacpcall: 2.125000
myluacpcall2: 7.813000
---
lua_cpcall: 6.593000
lua_pcall: 1.344000
lua_call: 1.109000
myluacpcall: 2.188000
myluacpcall2: 8.125000
(gcc 3.4/linux)
$ gcc -O2 lt.c -llua -lm
$ ./a.out
lua_cpcall: 2.100000
lua_pcall: 0.970000
lua_call: 0.590000
myluacpcall: 1.560000
myluacpcall2: 5.380000
---
lua_cpcall: 2.150000
lua_pcall: 0.950000
lua_call: 0.600000
myluacpcall: 1.600000
myluacpcall2: 5.420000
---
lua_cpcall: 2.110000
lua_pcall: 0.950000
lua_call: 0.580000
myluacpcall: 1.600000
myluacpcall2: 5.410000
(msvc2008/win)
$ cl -O2 lt.c lua51.lib
$ ./lt.exe
lua_cpcall: 5.828000
lua_pcall: 1.563000
lua_call: 0.937000
myluacpcall: 2.453000
myluacpcall2: 6.407000
---
lua_cpcall: 5.843000
lua_pcall: 1.172000
lua_call: 0.625000
myluacpcall: 2.563000
myluacpcall2: 7.140000
---
lua_cpcall: 5.938000
lua_pcall: 1.156000
lua_call: 0.844000
myluacpcall: 2.156000
myluacpcall2: 6.219000
---