金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  334 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks

C调用lua脚本的效率测试


以下代码以C语言为基准,测试了C调用Lua循环和循环调用Lua的效率。结论是不要频繁地穿越C/Lua边界.

代码整理自:http://blog.csdn.net/Tomorrow/archive/2008/06/11/2536884.aspx


#include <time.h>

extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}/* Lua解释器指针 */

const char LUA_SCRIPT[] =
    "function loop_add(a, b)            "
    "   local sum = 0                   "
    "   for i = 1, 10000000 do          "
    "       sum = sum + a + b           "
    "   end                             "
    "   return sum                      "
    "end                                "
    "                                   "
    "function add(a, b)                 "
    "   return a + b                    "
    "end                                "
    ;

// lua 脚本里面的函数由C调用
int use_lua_add(lua_State *L, const char *func_name, int x, int y)
{
    int sum;                        /* 通过名字得到Lua函数 */
    lua_getglobal(L, func_name);    /* 第一个参数 */
    lua_pushnumber(L, x);           /* 第二个参数 */
    lua_pushnumber(L, y);           /* 调用函数,告知有两个参数,一个返回值 */
    lua_call(L, 2, 1);              /* 得到结果 */
    sum = (int)lua_tointeger(L, -1);
    lua_pop(L, 1);
    return sum;
}

int main()
{
    int i, sum = 0;
    clock_t tStart, tStop;

    lua_State *L = lua_open();  /* opens Lua */
    luaL_openlibs(L);
    if (luaL_dostring(L, LUA_SCRIPT))  // Run lua script
    {
        printf("run script failed\n");
        lua_close(L);
        return -1;
    }

    sum = 0;
    tStart = clock();
    for (i = 0; i < 10000000; i++)
    {
        sum += 1 + 1;
    }
    tStop = clock();
    printf("C++: %dms.\nThe sum is %u.\n",
           (tStop - tStart) * 1000 / CLOCKS_PER_SEC, sum);

    sum = 0;
    tStart = clock();
    sum = use_lua_add(L, "loop_add", 1, 1);
    tStop = clock();
    printf("Lua loop_add: %dms.\nThe sum is %u.\n",
           (tStop - tStart) * 1000 / CLOCKS_PER_SEC, sum);

    sum = 0;
    tStart = clock();
    for (i = 0; i < 10000000; i++)
    {
        sum += use_lua_add(L, "add", 1, 1);
    }
    tStop = clock();
    printf("Loop lua add: %dms.\nThe sum is %u.\n",
           (tStop - tStart) * 1000 / CLOCKS_PER_SEC, sum);


    lua_close(L);
    return 0;
}

运行结果:

C++: 31ms.
The sum is 20000000.
Lua loop_add: 437ms.
The sum is 20000000.
Loop lua add: 2360ms.
The sum is 20000000.

 


posted on 2009-02-17 09:32 金庆 阅读(7911) 评论(4)  编辑 收藏 引用 所属分类: 1. C/C++2. 网游开发

评论

# re: C调用lua脚本的效率测试[未登录] 2009-02-17 11:05 smile
看来写脚本也得注意了  回复  更多评论
  

# re: C调用lua脚本的效率测试 2009-02-17 14:09 LOGOS
1.如果使用脚本,不在每一帧多次由C穿越到lua是没有意义的,这属于事件驱动的一种脚本使用方式。既然是利用脚本所拥有的灵活性,那么应该按需穿越,而不是限制穿越

2.lua慢于C/C++10倍以上,所以Lua loop_add的计时我没有异议。但是这个时间的主要部分是loop_add的运行耗时,而不是穿越耗时

3.Loop lua add的计时也是正确的,但是你从该计时认为穿越很耗费就是错误的。
为什么?因为你使用了“lua_getglobal(L, func_name);”,这个函数是C函数,负责查找和压栈,即你所谓的穿越中的一步,你用这个函数10000000次,字符串的解析和全局表的查找是很费时的,这里真正花在lua_call上的时间又有多少呢

有关优化调用lua函数的方法,可以参考我的
http://www.cppblog.com/darkdestiny/archive/2008/10/17/luafunction.html

  回复  更多评论
  

# re: C调用lua脚本的效率测试 2009-02-17 19:11 金庆
@LOGOS
有理。有空试试。  回复  更多评论
  

# re: C调用lua脚本的效率测试 2010-11-21 10:36 hu1010
没改之前
C++: 47ms.
The sum is 20000000.
Lua loop_add: 265ms.
The sum is 20000000.
Loop lua add: 1747ms.
The sum is 20000000.

改上楼上的方式(高效调用lua函数)
C++: 47ms.
The sum is 20000000.
Lua loop_add: 265ms.
The sum is 20000000.
Loop lua add: 1420ms.
The sum is 20000000.

单次是速度上没任何提升,Lopp lua add 还是有点提升,但效果不明显

楼上的高效调用Lua 函数,也没写明白,在网上一搜索,都一大把(都一样),貌似都是复制,粘贴,唉!
我将代码贴出来,

int add_handler;
int loop_add_handler;

lua_getglobal(L, "add"); /* 第一个参数 */
add_handler = luaL_ref( L , LUA_REGISTRYINDEX );

lua_getglobal(L, "loop_add"); /* 第一个参数 */
loop_add_handler = luaL_ref( L , LUA_REGISTRYINDEX );

// lua 脚本里面的函数由C调用
int use_lua_add_handler(lua_State *L, const int handler, int x, int y)
{
int sum; /* 通过名字得到Lua函数 */
lua_rawgeti( L, LUA_REGISTRYINDEX, handler);
//lua_getglobal(L, func_name); /* 第一个参数 */
lua_pushnumber(L, x); /* 第二个参数 */
lua_pushnumber(L, y); /* 调用函数,告知有两个参数,一个返回值 */
lua_call(L, 2, 1); /* 得到结果 */
sum = (int)lua_tointeger(L, -1);
lua_pop(L, 1);
return sum;
}

  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理