[erlang-questions] Deterministic playback of a simulation?

Enrique Paz <>
Fri May 18 08:45:14 CEST 2012


If I get it right, your issue is that the logged function calls might be in
the wrong order. Couldn't you add a timestamp to the call info you are
logging? erlang:now() or os:timestamp/0 (faster) return a timestamp up to
microseconds, then the only action left to do would be ordering your logs
before using them.


2012/5/18 Richard Evans <>

> I have a multiplayer simulation game running in erlang, involving
> multiple characters making decisions etc. Each game instance uses a
> few (currently, 4) erlang processes running concurrently,
> communicating with an AI simulator written in C.
>
> Everything is working well and I am enjoying using erlang.
>
> But there is one thing I am finding tricky.
>
> For QA purposes, I want to be able to record the exact sequence of
> function-calls, so I can play the game back exactly,
> deterministically.
>
> My current approach is this: I have a global ets table storing a list
> of function-calls. Then, whenever I was calling a function I want to
> record - instead of calling the function directly - I call a procedure
> which adds the function to the list of function-calls, and then calls
> it:
>
> call_and_store(Fun, Args) ->
>    add_to_script(Fun, Args);
>    apply(lobby, Fun, Args).
>
> add_to_script(Fun, Args) ->
>    Info = ets:info(script),
>    {size, Size} = lists:keyfind(size, 1, Info),
>    io:format("Inserting {~p,~p,~p}~n", [Size,Fun,Args]),
>    ets:insert(script, {Size, Fun, Args}).
>
> This approach does not seem to work well because of erlang's
> pre-emptive scheduling. If two concurrent processes both invoke
> call_and_store, then it is possible (and seems to actually be
> happening) that erlang's pre-emptive scheduler may stop processing one
> instance of call_and_store between execution of add_to_script and
> execution of apply. If this happens, the order of execution and the
> order of recorded function-calls will diverge, we don't have an
> accurate recording of the set of function-calls, and we won't be able
> to deterministically playback.
>
> So my question is: is there a way to prevent the scheduler from
> yielding during a block of code? Some way to insist the block is
> called as one unit, like this:
>
> call_and_store(Fun, Args) ->
>        !!!prevent_yielding,
>    add_to_script(Fun, Args);
>    apply(lobby, Fun, Args),
>        !!!allow_yielding.
>
> My guess is: no. This does not seem very erlangy.
>
> Alternatively, is there a different approach which can produce the
> desired list of function-calls? My current approach seems to go
> against the erlang grain, involving writing to a shared global table.
> Is there a better, more erlangy, way of doing this?
>
>
>
> thanks,
> ~Richard
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>



-- 
quique
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20120518/5e4df6ba/attachment.html>


More information about the erlang-questions mailing list