anchor.diff:      {Params, NextState} = eval_expr(Args, State, Env, WorkerProvider),
       apply(mzb_stdlib, Name, [NextState, Env, Meta | Params]).
   
  +-record(const_rate, {rate_fun, prev_value = undefined}).
  +-record(linear_rate, {from_fun, to_fun, prev_from, prev_to}).
  +
   -spec eval_loop([proplists:property()], [script_expr()], worker_state(), worker_env(), module())
       -> {script_value(), worker_state()}.
   eval_loop(LoopSpec, Body, State, Env, WorkerProvider) ->
  
positive.code:             {nil, State3};
          false ->
              RPSFun = fun (S) -> {undefined, S} end,
              looprun(ProcNum, TimeFun, Iterator, Spawn, {constant, RPSFun}, Body, WorkerProvider, State3, Env);
          #operation{args = [#constant{value = _, units = _} = RPS]} ->
              RPSFun = Evaluator(RPS),
              looprun(ProcNum, TimeFun, Iterator, Spawn, {constant, RPSFun}, Body, WorkerProvider, State3, Env);
          #operation{args = [#operation{name = think_time,
                                        args = [#constant{units = _} = Rate,
                                                #constant{units = _} = ThinkTime]}]} ->
  
negative.code:     end.
  
  looprun(1, TimeFun, Iterator, Spawn, Rate, Body, WorkerProvider, State, Env)  ->
      timerun(msnow(), 1, TimeFun, Iterator, Spawn, Rate, Body, WorkerProvider, Env, 1, State, 0);
  looprun(N, TimeFun, Iterator, Spawn, Rate, Body, WorkerProvider, State, Env) ->
      _ = mzb_lists:pmap(fun (I) ->
          timerun(msnow(), N, TimeFun, Iterator, Spawn, Rate, Body, WorkerProvider, Env, 1, State, I)
      end, lists:seq(0, N - 1)),
      {nil, State}.
  
  
  timerun(Start, Step, TimeFun, Iterator, Spawn, Rate, Body, WorkerProvider, Env, Batch, State, OldDone) ->
      LocalStart = msnow(),
      {Time, State1} = TimeFun(State),
      {ShouldBe, NewRate, Done, State2} = should_be(Rate, OldDone, LocalStart - Start, Time, State1),
  
      Remain = Start + trunc(ShouldBe) - LocalStart,
      GotTime = Start + trunc(Time) - LocalStart,
  
      Sleep = max(0, min(Remain, GotTime)),
      if
          Sleep > 0 -> timer:sleep(Sleep);
          true -> ok
      end,
      case Time + Start =< LocalStart + Sleep of
          true ->
              {nil, State2};
          false ->
              BatchStart = msnow(),
              NextState =
                  case Spawn of
                      false ->
                          case Iterator of
                              undefined -> k_times(Body, WorkerProvider, Env, State2, Batch);
                              _ -> k_times_iter(Body, WorkerProvider, Iterator, Env, Step, State2, Done, Batch)
                          end;
                      true ->
                          k_times_spawn(Body, WorkerProvider, Iterator, Env, Step, State2, Done, Batch)
                  end,
              BatchEnd = msnow(),
              NewBatch = batch_size(BatchEnd - BatchStart, GotTime, Sleep, Batch),
  
              timerun(Start, Step, TimeFun, Iterator, Spawn, NewRate, Body, WorkerProvider, Env, NewBatch, NextState, Done + Step*Batch)
      end.
  
  %-compile({inline, [should_be/5]}).
  should_be(#const_rate{rate_fun = F, prev_value = Prev} = RateState, Done, CurTime, Time, State) ->
      {Rate, State1} = F(State),
      NewDone =
          case {Rate, Prev} of
              {Prev, _} -> Done;
              {undefined, _} -> Rate * CurTime / 1000;
              {New, 0} -> New * CurTime / 1000;
              {New, undefined} -> New * CurTime / 1000;
              {New, _} -> Done * New / Prev
          end,
      ShouldBe =
          case Rate of
              undefined -> 0;
              0 -> Time * 2; % ShouldBe should be more than loop length "2" does not stand for anything important
              _ -> (NewDone * 1000) / Rate
          end,
      {ShouldBe, RateState#const_rate{prev_value = Rate}, NewDone, State1};
  should_be(#linear_rate{from_fun = FFun, to_fun = ToFun, prev_from = OldF, prev_to = OldT} = RateState, Done, CurTime, Time, State) ->
      {F, State1} = FFun(State),
      {T, State2} = ToFun(State1),
      NewDone =
          case {F, T} of
              {OldF, OldT} -> Done;
              {_, _} when OldF == undefined -> Done;
              {_, _} ->
                  Tm = CurTime,
                  A = F + (T - F) * Tm / (2 * Time),
                  B = OldF + (OldT - OldF) * Tm / (2 * Time),
                  Done *  A / B
          end,
      ShouldBe = time_of_next_iteration_in_ramp(F, T, Time, NewDone),
      {ShouldBe, RateState#linear_rate{prev_from = F, prev_to = T}, NewDone, State2}.
  
  %-compile({inline,[batch_size/4]}).
  batch_size(BatchTime, TimeLeft, Sleep, Batch) ->
      TimePerIter = max(0, BatchTime div Batch),
      if BatchTime * 4 > TimeLeft -> Batch div 2 + 1;
         (Sleep == 0) and (Batch < 1000000) -> Batch + Batch div 2 + 1;
         Sleep > 2*TimePerIter -> max(Batch - Batch div 16 - 1, 1);
         true -> Batch
      end.
  
  k_times(_, _, _, S, 0) -> S;
  k_times(Expr, Provider, Env, S, N) ->
      {_, NewS} = eval_expr(Expr, S, Env, Provider),
      k_times(Expr, Provider, Env, NewS, N-1).
  
  k_times_iter(_, _, _, _, _, S, _, 0) -> S;
  k_times_iter(Expr, Provider, I, Env, Step, S, Done, N) ->
  