lua-users home
lua-l archive

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


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
---