Алгоритмы, Наработки и Способности
Способ реализации:
Прочее
Тип:
Алгоритм
Версия Warcraft:
UjAPI v1.1.12.205+

Jass

Стандартный скриптовый (функционально/псевдо-объектно) ориентированный, строго-типизированный язык с автоматическим управлением памятью, для разработки карт в Warcraft 3, имеющий достаточно устаревший синтаксис и минимум современных парадигм.

lua

Процедурный динамически типизированный модульный язык с автоматическим управлением памятью. Язык был интегрирован в до Рефордж версии Ev3nt'ом. Данный язык имеет более современный синтаксис и имеет достаточное количество современных парадигм.

AngelScript

Интерпретируемый строго-типизированный, объекто-ориентированный язык программирования, разработанный специально для использования в качестве скриптового языка в приложениях. Был интегрирован совсем недавно мною (Unryze) с поддержкой пользователя GPSProlapse.

Для чего эта статья?

Очень часто заходят разговоры о скорости того или иного языка, однако все эти "доводы" построены буквально на воздухе, без особых тестов/проверок, что и хотелось уже решить раз и навсегда. Однако, сравнение конечно же синтетическое, и не предназначен для принижения производительности какого-либо из языков. Хочется так же добавить, что как только логика будет отходить от использования нативок игры, то в этих ситуациях lua и AngelScript будут всегда быстрее. А на сколько, это мы узнаем чуть позже. Для начала сделаем сравнение чего-то часто используемого.

Тесты CreateUnit

Jass
function TestFunctionDelayed takes nothing returns nothing
    local integer i = 0
    
    call RemoveUnit(CreateUnit(Player(0), 'Hpal', 0., 0., 0.))

    loop
        exitwhen i > 10
        call BenchmarkStart()
        call CreateUnit(Player(0), 'Hpal', 0., 0., 0.)
        call BenchmarkEnd()
        call ConsolePrint("Elapsed: " + BenchmarkGetElapsed(2) + "(ms) | " + BenchmarkGetElapsed(1) + "(us) | " + BenchmarkGetElapsed(0) + "(ns)\n")
        call BenchmarkReset()
        set i = i + 1
    endloop
endfunction

function OnMapInitDelayed takes nothing returns nothing
    call TimerStart(GetExpiredTimer(), .5, false, function TestFunctionDelayed)
endfunction

function InitTrig_InitTests takes nothing returns nothing
    call TimerStart(CreateTimer(), .01, false, function OnMapInitDelayed)
endfunction
lua
function TestFunctionDelayed( )
  RemoveUnit( CreateUnit( Player( 0 ), FourCC( "Hpal" ), 0., 0., 0. ) )

  for i = 0, 10, 1
  do
    BenchmarkStart( )
    CreateUnit( Player( 0 ), FourCC( "Hpal" ), 0., 0., 0. )
    BenchmarkEnd( )
    ConsolePrint( "Elapsed: " .. BenchmarkGetElapsed( 2 ) .. "(ms) | " .. BenchmarkGetElapsed( 1 ) .. "(us) | " .. BenchmarkGetElapsed( 0 ) .. "(ns)" .. "\n" )
    BenchmarkReset( )
  end
end

function OnMapInitDelayed( )
  TimerStart( GetExpiredTimer( ), .5, false, TestFunctionDelayed )
end

function main( )
  TimerStart( CreateTimer( ), .01, false, OnMapInitDelayed )
end

main( )
AngelScript
void TestFunctionDelayed( )
{
  RemoveUnit( CreateUnit( Player( 0 ), 'Hpal', 0.f, 0.f, 0.f ) );

  for ( int i = 0; i < 10; i++ )
  {
    BenchmarkStart( );
    CreateUnit( Player( 0 ), 'Hpal', 0.f, 0.f, 0.f );
    BenchmarkEnd( );
    ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" );
    BenchmarkReset( );
  }
}

void OnMapInitDelayed( )
{
  TimerStart( GetExpiredTimer( ), .5f, false, @TestFunctionDelayed );
}

void main( )
{
  TimerStart( CreateTimer( ), .01f, false, @OnMapInitDelayed );
}

Результаты CreateUnit

Итого мы получаем, что языки примерно одинаково справились с поставленной задачей. Данное сравнение не конечное и другие сравнения будут добавлены, но для более объективных тестов хотелось бы увидеть примеры от вас - читателей.

Тесты Скорости доступа к переменным

Jass
globals
    integer someInt
    integer array someIntArray
endglobals

function TestStupidShit takes nothing returns nothing
    local integer i = -1

    set someInt = 10000
    set someIntArray[ 8191 ] = 10000
    set uTest = CreateUnit( Player( 0 ), 'htow', -500., -500., .0 )
    set iTest = GetHandleId( uTest )

    call BenchmarkStart( )
    set i = 0
    call BenchmarkEnd( )
    call ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" )
    call BenchmarkReset( )

    call BenchmarkStart( )
    set i = someIntArray[ 8191 ]
    call BenchmarkEnd( )
    call ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" )
    call BenchmarkReset( )

    call BenchmarkStart( )
    set i = someInt
    call BenchmarkEnd( )
    call ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" )
    call BenchmarkReset( )
endfunction
lua
someInt = -1;
someIntArray = { };

function TestFunctionDelayed( )
  i = -1
  someInt = 100000
  someIntArray[8191] = 100000

  BenchmarkStart( )
  i = 0
  BenchmarkEnd( )
  ConsolePrint( "Elapsed: " .. BenchmarkGetElapsed( 2 ) .. "(ms) | " .. BenchmarkGetElapsed( 1 ) .. "(us) | " .. BenchmarkGetElapsed( 0 ) .. "(ns)" .. "\n" )
  BenchmarkReset( )

  BenchmarkStart( )
  i = someIntArray[ 8191 ]
  BenchmarkEnd( )
  ConsolePrint( "Elapsed: " .. BenchmarkGetElapsed( 2 ) .. "(ms) | " .. BenchmarkGetElapsed( 1 ) .. "(us) | " .. BenchmarkGetElapsed( 0 ) .. "(ns)" .. "\n" )
  BenchmarkReset( )

  BenchmarkStart( )
  i = someInt
  BenchmarkEnd( )
  ConsolePrint( "Elapsed: " .. BenchmarkGetElapsed( 2 ) .. "(ms) | " .. BenchmarkGetElapsed( 1 ) .. "(us) | " .. BenchmarkGetElapsed( 0 ) .. "(ns)" .. "\n" )
  BenchmarkReset( )
end
AngelScript
int someInt;
array<int> someIntArray(8192);

void TestFunctionDelayed( )
{
  int i = -1;
  someInt = 100000;
  someIntArray[8191] = 100000;

  BenchmarkStart( );
  i = 0;
  BenchmarkEnd( );
  ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" );
  BenchmarkReset( );

  BenchmarkStart( );
  i = someIntArray[ 8191 ];
  BenchmarkEnd( );
  ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" );
  BenchmarkReset( );

  BenchmarkStart( );
  i = someInt;
  BenchmarkEnd( );
  ConsolePrint( "Elapsed: " + BenchmarkGetElapsed( 2 ) + "(ms) | " + BenchmarkGetElapsed( 1 ) + "(us) | " + BenchmarkGetElapsed( 0 ) + "(ns)" + "\n" );
  BenchmarkReset( );
}

Результаты Скорости доступа к переменным

По итогу, lua и AngelScript примерно одинаковой скорости и быстрее чем Jass в 2~3 раза. В целом, можно ожидать общий прирост скорости над Jass может дойти до 5. Однако даже учитывая все эти нюансы, проекты, которые бы сильно почувствовали разницу от разницы в наносекундах - очень мало, но да, они есть. Однако чем больше данных будет обрабатываться без вовлечения движка игры, тем обработка будет быстрее. Один из примеров - это энумерация юнитов через массив, а не через Group API.
`
LOADING AD...
29
Данное сравнение не конечное и другие сравнения будут добавлены, но для более объективных тестов хотелось бы увидеть примеры от вас - читателей.
Довольно редкий, но показательный пример - кэш Z. Нужно пройтись по всей карте с шагом 8/16/32/64, получить высоту и положить в хт/таблицу/коллекцию.
Replies (3)
38
nazarpunk, тоесть мы сначала юзаем поиск z в рантайме, пока в фоне считается карта, а когда готово - переключаем низкоуровневые функции на работу с кешем?
29
ScorpioT1000, мы таким образом к примеру избавляемся от нативок. Но тест всё равно больше синтетический.
38
nazarpunk, в итоге рефордж со своим sd/hd сломал нахрен всю работу с Z в мультиплеере и твое предложение выглядит как маст ду для карт в рефордже с 3d геймплеем
20
A new version is out! Scroll to the resource
Исправлен тестовый код AngelScript под последнюю версию, где более нет нужды в FourCC ибо теперь есть поддержка равкодов.
Исправлен карта в архиве.
To leave a comment please sign in to the site.