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:
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:
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?
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 <richardprideauxev...@gmail.com>
> 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:
> 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:
> 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?
2012/5/18 Richard Evans <richardprideauxev...@gmail.com>:
[...]
> 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.
You could try to trace on the function calls with timestamps.
_______________________________________________
erlang-questions mailing list
erlang-questi...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
What about using erlang tracing facility. It hase some nice features. There will be zero inpact in production code. There will be zero inpact in production environment if you turn it on only in testing environment and also there is "automatic" ordering of events. I think it is best fit for purpose.
<richardprideauxev...@gmail.com> wrote: > 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:
> 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:
> 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?
> 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:
You can specify on how many nodes you want to acquire a lock - default is all connected nodes, but you can set it e.g. to [node()] if that suits you better.
On Fri, May 18, 2012 at 12:38 PM, Ulf Wiger <u...@feuerlabs.com> wrote:
> On 18 May 2012, at 04:36, Richard Evans wrote:
>> 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:
> You can specify on how many nodes you want to acquire a lock - default is all connected nodes, but you can set it e.g. to [node()] if that suits you better.