Априорная оценка «вычислений» относительно лимита операций
» Этап 1 пытаюсь оценить блок
integer INT = 0
...
function Code takes nothing returns nothing
TriggerSleepAction(0.)
  loop
    INT++
  endloop
endfunction

function PostCode takes nothing returns nothing
  real r
  TriggerSleepAction(0.3)
  printi(INT)
  r = 50000./INT - 1.
  printr(r)
endfunction
r = 0.166671
» Этап 2, подставляю коэффициент, чтобы исключить влияние счетчика
...
function PostCode takes nothing returns nothing
  real r
  TriggerSleepAction(0.3)
  printi(INT)
  r = (50000.-INT*0.166671)/(INT) - 1.
  printr(r)
endfunction
r = 0.
» Этап 3, описываю какую-то функцию, подсчитываю её "вес"
function test takes nothing returns nothing
...
endfunction
function Code takes nothing returns nothing
TriggerSleepAction(0.)
  loop
    test()
    INT++
  endloop
endfunction
r = 6.33408
» Этап 4 добавляю в базовый блок (INT++) еще действия
integer I = 0
function Code takes nothing returns nothing
TriggerSleepAction(0.)
  loop
    I++
    INT++
  endloop
endfunction
function PostCode takes nothing returns nothing
  real r
  TriggerSleepAction(0.3)
  printi(INT)
  r = (50000.)/(INT) - 1.
  printr(r)
endfunction
r = 1.166754
» Этап 5, подставляю коэффициент, чтобы исключить влияние базового блока
...
function PostCode takes nothing returns nothing
  real r
  TriggerSleepAction(0.3)
  printi(INT)
  r = (50000.-INT*1.166754)/(INT) - 1.
  printr(r)
endfunction
r = 0.
» Этап 6, считаю "вес" функции test() снова
function Code takes nothing returns nothing
TriggerSleepAction(0.)
  loop
    test()
    I++
    INT++
  endloop
endfunction
r = 4.667582

Таким образом, оценка меняется в зависимости от базового блока. Это значит, что конечная сложность блока не равна последовательной сумме отдельных составляющих, поскольку для следующего блока опорным будет блок из всех предыдущих.
На самом деле это не очень страшно. При увеличении базового блока уменьшается оценка. Это соответствует, как если бы виртуальная машина разгонялась, и следующие операции «легче» выполнялись. Из этого должно следовать, что сумма полученных таким образом оценок больше реальной итоговой (ограничение сверху). Но на практике столкнулся с необычным эффектом:
» Этап 1
real LIM
boolexpr array FIL

function test28 takes integer n returns nothing
endfunction

function test takes nothing returns boolean
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
  INT++
  test28(0)
  LIM = LIM + 6.166836
  return true
endfunction

function q_update takes nothing returns nothing
  LIM = 1.333329
  loop
  exitwhen LIM > 50000.
    ForceEnumPlayers( EmptyForce, FIL[II[0]] )
    LIM = LIM + 3.833329 + 25.
  endloop
endfunction

define {
  Time = 0.025
}

function Trig_init_Actions takes nothing returns nothing
  timer t = CreateTimer()
  FIL[0] = Filter(function test)
  TimerStart(t,Time,true,function q_update)
endfunction
FPS в районе 64, как и положено
» Этап 2, масштабирование
real LIM
boolexpr array FIL

function test27 takes integer n returns nothing
endfunction

function test26 takes integer n returns nothing
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
  I = I + 0
  test27(0)
  LIM = LIM + 3.166836
endfunction

function test25 takes integer n returns nothing
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
  I = I + 0
  test26(0)
  LIM = LIM + 6.166836
endfunction

function test24 takes integer n returns nothing
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
  I = I + 0
  test25(0)
  LIM = LIM + 6.166836
endfunction

function test23 takes integer n returns nothing
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
  I = I + 0
  test24(0)
  LIM = LIM + 6.166836
endfunction

function test takes nothing returns boolean
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
  INT++
  test23(0)
  LIM = LIM + 6.166836
  return true
endfunction

function q_update takes nothing returns nothing
  LIM = 1.333329
  loop
  exitwhen LIM > 50000.
    ForceEnumPlayers( EmptyForce, FIL[II[0]] )
    LIM = LIM + 3.833329 + 25.
  endloop
endfunction

define {
  Time = 0.025
}

function Trig_dfhfjfv_Actions takes nothing returns nothing
  timer t = CreateTimer()
  FIL[0] = Filter(function test)
  TimerStart(t,Time,true,function q_update)
endfunction
FPS падает до 57-63
» Вычисление коэффициента для test()
real R = 0.
integer I = 0

function test takes integer n returns nothing
  integer i = 0, j = 0, k = 0, d = 0, e = 0, f = 0
endfunction

// получаем 6.1668

function Code takes nothing returns boolean
  TriggerSleepAction(0.)
  loop
    I = I + 0
    test(0)
    R = R + 0.
    
    INT++
  endloop
  return true
endfunction

function PostCode takes nothing returns nothing
  real r
  TriggerSleepAction(0.3)
  printi(INT)
  r = (50000-INT*0.166671)/(INT) - 1.
  printr(r)
endfunction
r = 6.1668

Как объяснить и детектировать этот эффект?
PS у себя на карте я получаю просадку на 10-20fps из за таких неясных закономерностей. И, следовательно, не могу выложить для вас новый ресурс.

Лучший ответ:
Ответ. Кроме вычислительного предела есть еще лимит создания новых потоков. Оба вида загруженности вызывают характерное падение мощности. Но попытка оценить работу с помощью только одного критерия будет заведомо ошибочной.


Views: 318

Hate #1 - 11 months ago 1
Голосов: +1 / -0
вычислять время используя TriggerSleepAction это конечно сильно
Vlod #2 - 11 months ago 0
Голосов: +0 / -0

Ответ. Кроме вычислительного предела есть еще лимит создания новых потоков. Оба вида загруженности вызывают характерное падение мощности. Но попытка оценить работу с помощью только одного критерия будет заведомо ошибочной.