Your comparison is not fair because your Lua scripts are badly written.
You need to declare functions and variables as local, e.g. "local function fib(n) ...".
There is a better collection of benchmarks for various languages and better measurement here:
http://shootout.alioth.debian.org/gp4sandbox/
[Sorry for writing in English]
mike_lua
Hello, Mike! Welcome to the russian gamedeveloper`s site.
Thank you for LuaJIT. It is really great! You are doing a right work.
Best regards.
Если уж считать рекурсивно, то хвостовая рекурсия рулит. Заодно проверка интерпретатора...
function fib(n) return fib_tail(n, 1, 0) end function fib_tail(n, next, result) if n == 0 then return result end return fib_tail(n - 1, next + result, next) end print(fib(10000))
Yes, but if you want to compare different languages then you have to keep the algorithm the same.
There are obviously much faster ways to compute fib(), ack() and so on ...
The important thing for Lua (and more so for LuaJIT) is to use local everywhere.
Global vars and global functions are slow (and bad style).
Here is a comparison for the naive algorithm:
local function fib(n) if n < 2 then return 1 end return fib(n-2) + fib(n-1) end print(fib(tonumber(arg[1])))
fib(35) global: lua: 11.49s, luajit -O: 2.15s
fib(35) local: lua: 10.46s, luajit -O: 1.55s (!)
Вот интересно... холивар называется как AngelScript VS LUA
Но вот тестов AngelScript я тут ниодного ненашел... интересный такой холиварчик в одни ворота.
А как по времени Squirell или C-TALK?
В AngelScript Мне нравится подобная конструкция:
// C++ code //эти перемееные будут изменятся скриптом, но будут доступны программе. int counter = 5; float time = 0; engine->RegisterGlobalProperty("int counter", &counter); engine->RegisterGlobalProperty("const float time", &time);
// AngelScript code void DoSomething() { if( time > 1 ) counter += 2; else counter++; }
А еще нарвится биндинг функций:
// C++ code float CObject::Sum(float a, float b) { return a + b; } engine->RegisterObjectMethod("object", "float Sum(float, float)", asMETHOD(CObject, Sum), asCALL_THISCALL);
// AngelScript code void Test() { object o; float sum = o.Sum(1.0f, 2.0f); }
Т.е. абсолютно ненужно переделывать существующие функции под скрипт.
И никаких заморочек со стеком внутри функций движка=)
Насчет скорострельности незнаю, непроверял, пока просто изучаю документацию.
А LUA может биндить функции только типа
//C++ int testfunc( lua_State* luaVM) { lua_pushnumber( luaVM, 0 ); }; lua_register( luaVM, "Mtestfunc", testfunc );
Ознакамливаюсь с докой по TOLUA, вроде есть подобные упоминания...
Вроде бы тоже может и переменные и функции такиеже биндить... Правильно? или неможет?(
PS. Насчет того что AngelScript.Lib весит 2 мегабайта! соглашусь, так и есть. И Dll имеет размер 660кб.
Но вся проблема имеет примитивные корни! Нужно при компиляции проекта установить не Debug, а RELEASE!
И Lib получится 780кб, а DLL 300кб... Хехехе, не ну вы блин отмочили про 2 метра =)
если использовать luabind, то биндинг выглядит так:
// class registration module(L)[ class_<CObject>("CObject") .def("Sum",&CObject::Sum) ];
Примечание: если есть несколько функций с именем Sum, то тогда надо написать полную сигнатуру функции:
// class registration module(L)[ class_<CObject>("CObject") .def("Sum",(float (CObject::*)(float,float))(&CObject::Sum)) ];
В принципе, регистрацию класса можно сделать и по частям.
Кстати, по-моему, boost::python предоставляет аналогичные возможности биндинга для питона.
Проверил AngelScript
Вычисление фибоначи:
int32 fib(int32 n) { if (n == 0) return 0; else if (n == 1) return 1; return (fib(n-1) + fib(n-2)); }; void main() { print(fib(40)); }
as = 2минуты 58секунд
Тестировалось на: "AMD64 SMP3000+/s939/MB ati express200p/512DDR400/winxp/vc6++"
Дмитрий Ясенев
>Кстати, по-моему, boost::python предоставляет аналогичные возможности биндинга
>для питона.
угу:
void export_application() { class_<win_app>("application", init<boost::python::object &>()) .def("run", &win_app::run) .def("close", &win_app::close) .def("switch_screen_mode", &win_app::switch_screen_mode) .add_property("title", &win_app::title, &win_app::set_title) .add_property("width", &win_app::width) .add_property("height", &win_app::height) .add_property("base_width", &win_app::base_width) .add_property("base_height", &win_app::base_height) .add_property("fullscreen", &win_app::fullscreen) .add_property("win_handle", &win_app::win_handle) .add_property("time", &win_app::time) .add_property("dt", &win_app::dt) .add_property("fps", &win_app::fps) .add_property("average_fps", &win_app::average_fps) .add_property("fps_upgrade", &win_app::fps_upgrade) ; def("module_path", module_path); def("full_module_name", full_module_name); def("full_exe_name", full_exe_name); def("sys_info", get_os_cpu_info); def("display_name", display_name); def("build_info", get_build_info); def("file_version_info", get_file_version_info, gfvi_overloads()); }
Плюс там еще есть boost::python::object можно писать "почти на питоне" в C++ коде:
dict py_symbols(py_eval(run_str)); while(py_symbols) { tuple kv = py_symbols.popitem(); char_t key = extract<char_t>(kv[0]); tuple value(kv[1]); fdata fd; fd.x = extract<int>(value[0]); fd.y = extract<int>(value[1]); fd.w = extract<int>(value[2]); fd.h = extract<int>(value[3]); symbols_[key] = fd; }
>Кстати, по-моему, boost::python предоставляет аналогичные возможности биндинга
>для питона.
Luabind делался по образу и подобию boost::python (см. /luabind/doc/docs.html, в конце документа)
Есть еще один скриптовый язык, набирающий популярность: GameMonkey. Вот features с их сайта:
- Small code base. Compiled code may use about 50kb of RAM. Less when tweaking or sharing with application.
- Compile source code at run time, or link to precompiled libs.
- Lightweight, native threading.
- Soft real-time incremental garbage collection. Controllable memory footprint. No painful reference counting.
- Easy to bind C\C++ functions and call script from C\C++.
- Runtime debugging and reflexion support.
- C style syntax.
- Competitive performance when compared to other scripting languages for both CPU and Memory usage. Speed is a trade off for flexibility and simplicity.
- Easily modifiable as it is written in C++ and uses Flex and Bison.
http://www.somedude.net/gamemonkey/
Сам не пробовал, просто даю ссылку для любителей всё тестировать.
Тэсты в режиме Release
использован VC6
Версия AngelScript 2.12.0
Версия LUA 5.1.3
Тэст фибоначи
//LUA local function fib(n) if (n == 0) then return 0 elseif (n == 1) then return 1 end return fib(n-1) + fib(n-2) end print(fib(40))
//AngelScript int32 fib(int32 n) { if (n == 0) return 0; else if (n == 1) return 1; return (fib(n-1) + fib(n-2)); }; void main() { print(fib(40)); };
//C++ (asm compiled) int fib(int n) { if (n == 0) return 0; else if (n == 1) return 1; return (fib(n-1) + fib(n-2)); };
Тест LUA:
функция global, время выполнения 223 719 ms
функция local, время выполнения 196 250 ms
Тест AS:
Статически линкуемая release библиотека.lib, время выполнения 223 140 ms
Сборка с подключеными исходниками, время выполнения 241 203 ms
Сборка с подключеными исходниками, Mod_switch для VM, время выполнения 284 890 ms
Тест С++:
Время выполнения 3 125 ms
Примечание: Mod_switch сделан мной для эксперимента, представляет собой разделение switch в VM на несколько частей, т.е. посути интересен только мне ;)
На паскале в 2000м это давало прирост, сейчас на С наоборот замедлило...
Тэсты в режиме Release
использован VC6
Версия AngelScript 2.12.0
Версия LUA 5.1.3
Тэст фибоначи 2
//LUA function fib(n) if n < 2 then return 1 end return fib(n-2) + fib(n-1) end print(fib(40))
//AngelScript int32 fib(int32 n) { if (n < 2) return 1; return (fib(n-1) + fib(n-2)); }; void main() { print(fib(40)); };
Тест LUA:
функция global, время выполнения (40) 195 484 ms
функция global, время выполнения (30) 1 625 ms
функция local, время выполнения (40) 169 859 ms
функция local, время выполнения (30) 1 437 ms
Тест AS:
Статически линкуемая release библиотека.lib, время выполнения (40) 190 500 ms
Статически линкуемая release библиотека.lib, время выполнения (30) 1 608 ms
Сборка с подключеными исходниками, время выполнения (40) 199 813 ms
Сборка с подключеными исходниками, время выполнения (30) 1 891 ms
Сборка с подключеными исходниками, Mod_switch для VM, время выполнения (40) 231 282 ms
Тэсты в режиме Release
использован VC6
Версия AngelScript 2.12.0
Версия LUA 5.1.3
Тэст Аккермана
//LUA local function Ack(M, N) if (M == 0) then return( N + 1 ) end if (N == 0) then return( Ack(M - 1, 1) ) end return( Ack(M - 1, Ack(M, (N - 1))) ) end print(Ack(3,11))
//AngelScript int32 ack(int32 m,int32 n) { if (m == 0) return n+1; if (n == 0) return ack(m-1,1); return ack(m-1,ack(m,(n-1))); }; void main() { print(ack(3,11)); };
Тест LUA:
функция global, (3,11) Stack overflow
функция global, время выполнения (3,10) 30 922 ms
функция local, (3,11) Stack overflow
функция local, время выполнения (3,10) 26 984 ms
Тест AS:
Статически линкуемая release библиотека.lib, время выполнения (3.10) 32 204 ms
Статически линкуемая release библиотека.lib, время выполнения (3.11) 129 313 ms
Сборка с подключеными исходниками, время выполнения (3.10) 37 031 ms
Сборка с подключеными исходниками, время выполнения (3.11) 145 422 ms
Сборка с подключеными исходниками, Mod_switch для VM, время выполнения (3.11) 145 500 ms
Тэсты в режиме Release
использован VC6
Версия AngelScript 2.12.0
Версия LUA 5.1.3
Тэст фибоначи 3
//LUA function fib_tail(n, next, result)\n" if n == 0 then return result end\n" return fib_tail(n - 1, next + result, next)\n" end function fib(n) return fib_tail(n, 1, 0) end print(fib(40000))
//AngelScript int32 fib(int32 n) { return fib_tail(n,1,0); }; int32 fib_tail(int32 n,int32 next,int32 r) { if (n == 0) return r; return fib_tail(n-1,next + r,next); }; void main() { print(fib(40000)); }
Тест LUA:
Bремя выполнения 31 ms
Ответ имеет некорректное значение равное 1.#INF
Как решить эту проблему?!
Хотя если в пределах 400, то ответ выводится корректно, с заоблачным числом...
Время на 400 переборов тратится <1ms.
Тест AS:
Статически линкуемая release библиотека.lib, время выполнения 90 234 ms
Сборка с подключеными исходниками, время выполнения 99 172 ms
Сборка с подключеными исходниками, Mod_switch для VM, время выполнения 98 859 ms
Тэсты в режиме Release
использован VC6
Версия AngelScript 2.12.0
Версия LUA 5.1.3
Тэст Калькулятор
//LUA local function calc(n) for i = 1,n do res = i*5 + 12/(i+1) - i*(i+2) end return res end print(calc(30000000))
//AngelScript double calc(int32 n) { float res; //модификация double int32 i; //модификация double for (i = 1;i<n;++i) { res = i*5 + 12.0f/(i+1) - i*(i+2); }; return res; }; void main() { print(calc(30000000)); };
Тест LUA:
функция global, время выполнения 16 984ms (ответ -8.99999991e+014)
функция local, время выполнения 17 000ms
Тест AS:
Статически линкуемая release библиотека.lib, время выполнения 21 453 ms (ответ -9e+014) версия с double
Статически линкуемая release библиотека.lib, время выполнения 17 422 ms (ответ 195..что-то там) как в примере
Сборка с подключеными исходниками, время выполнения 17 610 ms
Сборка с подключеными исходниками, Mod_switch для VM, время выполнения 22 859 ms
Тема в архиве.