www.mudconnector.su https://forum.mudconnector.su/ |
|
mud design-concepts (расширяемость) https://forum.mudconnector.su/viewtopic.php?f=16&t=244 |
Страница 2 из 3 |
Автор: | omlin [ Пт ноя 19, 2010 10:27 pm ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
Эрендир, всё-таки вы неверно поняли, видимо Lua - это встраиваемый язык, он существует в контексте вашего приложения, и следовательно, вы должны с ним взаимодействовать. Именно для этого предназначено Lua C API Когда вы хотите выполнить в Lua код Код: foo={} for i = 1, 10^6 do foo.bar=10 end из вашего C-приложения, вы должны написать: Код: char *code = "for i = 1, 10^6 do foo.bar = 10 end"; luaL_dostring(luaState, code); Справка по lua_dostring и это действительно будет выполняться недолго почему? потому что, надо понимать, что здесь происходит на самом деле: 1) вызов библиотеки луа, передача в неё одной строки (на это на самом деле тоже тратится время) 2) луа парзит строку (на это тратится время!!), но т.к. строка в данном случае недлинная, парзится она довольно быстро, и преобразуется в байт-код 3) луа выполняет полученный байт-код, и на это тоже тратится время, впрочем это уже происходит очень быстро но наша задача в другом наша задача заключается в том, чтобы передать наши объекты в луа к примеру, у нас в c есть некий объект foo, у него есть свойство-массив с миллионом элементов: int Bar[1000000]; мы должны создать такой же объект в луа мы можем сделать это примерно так: Код: sprintf(code, " foo = {} foo.Bar[0] = %d foo.Bar[1] = %d foo.Bar[2] = %d foo.Bar[3] = %d foo.Bar[4] = %d --- .... foo.Bar[999999] = %d", foo.Bar[0], foo.Bar[1], foo.Bar[2], foo.Bar[3], ... foo.Bar[999999]); luaL_dostring(luaState, code); представьте, сколько луа будет парзить такую строку? но, это еще не все! на самом деле, в контексте мада, событий множество, все они дискретны, для каждого события должен быть отдельный вызов луа!! поэтому, фактически, нельзя будет передать 1 гигантскую строку. фактически, придется делать много вызовов. например, так: Код: for (int i = 1; i<10000; i++) { sprintf(code, " foo = {} foo.Bar[%d] = %d foo.Bar[%d] = %d foo.Bar[%d] = %d foo.Bar[%d] = %d foo.Bar[%d] = %d --- .... foo.Bar[%d] = %d", i, foo.Bar[i], i+1, foo.Bar[i+1], i+2, foo.Bar[i+2], i+3, foo.Bar[i+3], ... i+9, foo.Bar[i+9]); luaL_dostring(luaState, code); } вот, теперь у нас еще вдобавок ко всему 10к вызовов. и теперь это уже работает вообще страшно долго. как раз чтобы таким образом не извращаться, для C API придумали функцию lua_setfield которая позволяет делать это всё быстрее кароче идет работа напрямую с луа-стеком, минуя парзинг данных и вот даже несмотря на все эти оптимизации, всё равно присваивание таблице 1 млн. значений, работает 7 секунд. |
Автор: | Эрендир [ Сб ноя 20, 2010 2:31 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
я всё это как бы понимаю, хотя сам практически не занимался именно интеграцией Луа в Си. Так вот, слегка порывшись по мануалам и прочим интернетам я родил следующий код: Код: #include <iostream> extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } void report_errors(lua_State *L, int status) { if ( status!=0 ) { std::cerr << "-- " << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); // remove error message } } int main(int argc, char** argv) { for ( int n=1; n<argc; ++n ) { const char* file = argv[n]; lua_State *L; L = L = luaL_newstate(); luaL_openlibs(L); std::cerr << "-- Loading file: " << file << std::endl; int s = luaL_loadfile(L, file); lua_newtable(L); for (int i=0; i < 1000000; i++){ lua_pushstring(L, "bar"); lua_pushnumber(L, 10); lua_rawset(L, -3); } lua_setglobal(L, "foo"); lua_newtable(L); for (int i=0; i < 1000000; i++){ lua_pushnumber(L, i); lua_pushnumber(L, i*2); lua_rawset(L, -3); } lua_setglobal(L, "t"); if ( s==0 ) { // execute Lua program s = lua_pcall(L, 0, LUA_MULTRET, 0); } report_errors(L, s); lua_close(L); std::cerr << std::endl; } return 0; } компилировать так: Код: g++ test.cpp -o test -pedantic -Os -Ipath/to/Lua/include/ -Lpath/to/Lua/lib/ -llua5.1 теперь нужен ещё test.lua: Код: print(foo) print(foo.bar) print(t) print(t[1],t[999999]) запускать так: Код: test test.lua выполнение кода длится 0.333 секунды, и это включая парсинг и компиляцию скрипта test.lua. (незначительного прироста производительности можно добится использованием `lua_createtable(L,1000000,0);` для второй таблицы) При всё при этом сначала 10^6 раз выполняется код из Вашей статьи (`Measure("LuaDLL.lua_settable", 1000000, () =>`), а потом ещё заполняется миллион разных полей для новой таблицы. Что возвращает нас к моему утверждению: ни Луа, ни Lua C API не виноваты в том, что Ваша программа работает очень медленно. |
Автор: | omlin [ Сб ноя 20, 2010 4:22 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
вынужден признать, дело было, по всей видимости, действительно не в бобине (не в парзинге). на самом деле спасибо большое, что открыли глаза на это заблуждение. но проблемы с производительностью всё равно имеются. я подготовил вот такой код (на основе Вашего): Код: #include <iostream> #include <ctime> extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } int main(int argc, char** argv) { lua_State *L; L = L = luaL_newstate(); char s[255]; lua_newtable(L); clock_t t0 = clock(); for (int i=0; i < 1000000; i++){ // тут тестим } clock_t t1 = clock(); std::cout << "time: " << (double)(t1 - t0) / CLOCKS_PER_SEC << std::endl; lua_close(L); } вместо "// тут тестим", вписываю, последовательно, следующие вещи: Код: sprintf(s, "bar%d", i); lua_pushstring(L, s); lua_pushnumber(L, i*3); lua_settable(L, -3); time: 6.343 Опа! 6 секунд всплыло... Но может, это sprintf? Проверим: Код: sprintf(s, "bar%d", i); time: 1.813 sprintf, да не совсем. 4.5 секунды остаётся на луа... А ведь при этом, вариант: Код: lua_pushstring(L, "bar"); lua_pushnumber(L, i*3); lua_settable(L, -3); time: 0.265 работает очень быстро. также быстро работает и вот такой вариант: Код: lua_pushnumber(L, i); lua_pushnumber(L, i*3); lua_settable(L, -3); time: 0.281 , НО!! Код: lua_pushnumber(L, i*2); lua_pushnumber(L, i); lua_settable(L, -3); time: 1.39 и еще: Код: lua_pushnumber(L, 1000000-i); lua_pushnumber(L, i*3); lua_settable(L, -3); time: 0.968 Интересные, в целом, результаты. К сожалению, нет особо времени смотреть, что там в луа происходит, но видимо какой то кэш или хэш у них там есть, на обращение к филду... Это, на самом деле, очень хорошо, думаю, многие проблемы с производительностью можно решить, если держать пару глобальных переменных постоянно в стеке (типов монстр, предмет, и т.п.), и в дальнейшем использовать для передачи данных именно их, а не вновь создаваемые таблицы. Резюмируя Эрендир в конечном итоге оказался прав. Пожалуй, проблемы с производительностью в луа не критичны даже для реализации выносных скиллов/спеллов. |
Автор: | Эрендир [ Сб ноя 20, 2010 4:57 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
Рад, что мне удалось Вас убедить! И теперь уже видимо [offtop]: первый пример (`sprintf(s, "bar%d", i);`) можно ускорить примерно вдвое, если вместо lua_newtable(L); использовать lua_createtable(L,0,1000000); также он естественно самый медленный: сначала в куче создаётся миллион строк вида "bar%d", а потом наша тестовая таблица последовательно раздувается (пересчитывается non-array часть) во время заполнения (это можно избежать с lua_createtable ) пример с заполнением каждого второго (i*2) индекса можно ускорить либо за счёт (временного) места (lua_createtable(L,2000000,0);) (и потом задержка на итерации GC), либо посчитать руками, какого размера array часть, и какого non-array будет у такой таблицы. пример с заполнением с конца (1000000-i) ускоряется аналогично. [/offtop] [offtop] И да, я сам не был уверен в результатах, пока не занялся тестами, и, признаться, увидев Ваш пост про 7 секунд поначалу испугался: я всё лелею мечту понемножечку доклепать движок на чистом Луа (+luasocket и т.п., ессно), и если бы он тормозил даже с 10 игроками, это было бы ну очень обидно [/offtop] |
Автор: | Харч [ Сб ноя 20, 2010 9:31 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
Извините, я, как новичок в создании мадов, не знаю, Lua - специальный язык написанный для скриптинга мадов? |
Автор: | Эрендир [ Сб ноя 20, 2010 6:17 pm ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
http://www.google.com/search?q=lua |
Автор: | omlin [ Вс ноя 21, 2010 12:45 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
LUA - это один из популярнейших встраиваемых языков для игр. Используется, в частности, в WOW. Встраиваемый язык означает, что вы можете использовать луа в качестве языка для триггеров, или других нужд, предполагающих необходимость создания скриптов. Эрендир писал(а): первый пример (`sprintf(s, "bar%d", i);`) можно ускорить примерно вдвое, если вместо lua_newtable(L);... Первый пример наиболее близок к реальности из всех перечисленных, однако, как я уже упоминал, всё-таки в реальности скорее будет что-нибудь типа 5к созданий таблицы с 20 полями. Всё-таки, один объект с 1 млн. полей это абстракция. Так что выигрыша в производительности тут врядли удастся добиться именно с помощью lua_createtable. Нет, тут надо по-другому действовать. Объекты передаются строго определенных типов. В частности, это мобы, комнаты, и предметы. Причем, за один раз таблиц каждого вида может передаваться, наверное, не больше трех. Например, FIGHT-триггер требует self и actor, оба типа "монстр". С другой стороны, после отрабатывания триггера эти переменные становятся ненужными, а значит, их можно либо совсем удалить из кучи, либо использовать повторно. Если заранее создать по 3 таблицы каждого возможного типа, сохранить их в некоторых глобальных переменных, и затем, при передаче данных использовать именно эти таблицы, то скорость работы, по всей видимости, должна увеличиться в сотни раз. Эрендир писал(а): я всё лелею мечту понемножечку доклепать движок на чистом Луа (+luasocket и т.п., ессно) Может быть, это и реально, но очень напоминает забивание гвоздей микроскопом - только потому, что микроскоп нравится и с ним привычнее работать:) Ну в самом деле, язык должен выбираться под нужды. Потому что язык - это инструмент. Хороший, подходящий инструмент увеличивает скорость работы, и качество работы, в разы и даже на порядки. Ну банальный пример, в луа нет настоящего ООП, это не критично для скриптов, но это критично для большого проекта. Наследование, инкапсуляция, полиморфизм - всё это помогает и в том, чтобы создать гибкий и легко расширяемый проект. Строгая типизация (как в С++, С# и java) позволяет отловить многие ошибки на стадии компиляции. На самом деле компиляция - это первый юнит-тест! В луа с типизацией всё намного проще, хотя луа конечно получше в этом плане, чем, к примеру, перл. Подготовленные и проверенные механизмы для юнит-тестов, руководства, мануалы, библиотеки, комьюнити - во всем этом С++, java и С# тоже выигрывают. Ну и всякий синтаксический сахар, как например, Linq, Generic'и, перегрузка операторов... Подумай:) Мад на луа это ж ведь как раз тот самый велосипед с квадратными колесами, который делает сейчас Харч, только в добавок ко всему ты лелеешь этот велосипед собрать при помощи микроскопа Ребяты! Если вам интересно работать над мадом, если у вас есть светлая голова, давайте объединяться. Да, при этом придется идти на уступки, учиться работать в команде, иногда - делать вещи, которые делать не очень хочется. Но это полезные навыки, и на работе, и в семейной жизни, и вообще в жизни. И главное, ведь есть совершенно реальный шанс прочувствовать и увидеть, что результат вашей работы оценен, используется и нравится конечным пользователям... |
Автор: | Эрендир [ Вс ноя 21, 2010 1:21 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
Не буду спорить про микроскоп и прочие юнит-тесты... Поживём-увидим, как говорится. Или не увидим, если я и дальше буду лениться. Одно замечание: Луа не акроним. Писать ЛУА неправильно. Луа означает Луна (по-португальски, емнип). По-поводу комманды: опыт объединения исключительно через интернет, без каких-либо других объединяющих факторов лично у меня отрицательный. Причём, емнип, дважды. Правда и я тогда был помладше и глупее, но всё же настроение относительно таких команд скептическое. |
Автор: | omlin [ Вс ноя 21, 2010 1:47 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
Однако же, если программист, то всё равно куда от команды? Разве что в суппорт на какое нибудь производство, а это буэ страшное, лучше даже не соваться. Убивает мозги за полгода, гарантированно. Я уж не говорю про сисадминство... Самое классное это конечно тимлидом в стартапах. Но, опять же, тимлид => команда Нет, если хочется программировать, от команды никуда. Я прошел весь этот путь, начинал в Хьерварде, потом писал собственный мад в одиночку, потом в малой команде, потом еще один проект мада писали - тоже с парой ребят, ну в итоге пришел в Адан... Причем, Хьервард был как раз неприятным опытом. Полгода не было у меня возможности вылезать в мад, прихожу через полгода, и мне говорят что-то типа такого: у нас новый главбилдер (мой бывший билдер), пиши ему письмо, он посмотрит твою зону. На самом деле, всё очень зависит от руководителя проекта. Но если вы видите, что к примеру в былинах куча народу работает, ну ведь неспроста? Значит, лидер там, с большой вероятностью, умелый. И кстати, после Хьерварда я пришел практически к таким же выводам, и начал писать сам. Но две попытки подряд для меня оказались достаточными, чтобы понять, что создание полномасштабного мада, это задача не для одного человека. Даже если движок за год накатать, а мир кто делать будет? А редактор мира? А справку? А баланс? А сайт?... Даже, на самом деле, не для двух человек. И еще нельзя забывать современные реалии, когда мады уже вышли из пика своей популярности, и чтобы в них играли, придется немало усилий приложить. Нет, никуда без команды в мадах, никуда. |
Автор: | Эрендир [ Вс ноя 21, 2010 2:34 am ] |
Заголовок сообщения: | Re: mud design-concepts (расширяемость) |
Цитата: Однако же, если программист, то всё равно куда от команды? а я не програмист Но опять же, я не против команды вообще, я против команды, собранной исключительно через интернет, т.к. опыт такого рода у меня печальный. Я рискну предположить, что в Былинах работает куча людей, потому что есть некое ядро, несколько человек, знакомых друг с другом в реале, условно "вокруг которых" держаться остальные члены команды. Цитата: понять, что создание полномасштабного мада, это задача не для одного человека. О, я прекрасно отдаю себе в этом отчёт, и мой план примерно таков: 1. Сделать движок, минимальный кусочек мира, более-менее сбалансированную механику,справку на всё что есть. 2. Порекламировать такой набросок, позвать желающих в билдеры 3. ?????? 4. PROFIT!!! (самое сложное тут, несомненно, пункт 4 ) Пока же я нахожусь где-то в начале очередной итерации номера 1, части а: движок |
Страница 2 из 3 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |