Hi,
I miss an ISOMICRO profile of Web Prolog, a profile
that can run on small embedded devices, and only
single threaded. Like Python can do for example.
I deleted my previous post, since it drifted into
high performance computing. It was a reaction of
mine, to these results and how they were viewed.
But the results have a few drawbacks. They use a highly
specialized π-WAM Prolog subset and a highly specialized
Hack VM backend. Also the ping pong code was optimized.
So I guess this high performance view is too specific
for the actor model. So to get a more general comparison,
I tried something else. I used a Python implemented Prolog
and a Python asyncio.Future implemented one element
channels, the later equals SWI-Prolog queues with max_size=1.
Finally I used the classical ping pong. Now with PyPy as the Python
runtime the results are, 6x times faster than the shared database
on a SWI-Prolog server provided by Torbjörn Lager. Difficult
to judge maybe my machine is just 6x times faster? One could
install PyPy, download Dogelog Player and run it on the server:
?- between(1,3,_), time(ping_pong(100000)), fail; true.
% Time 812.000 ms, User 54 %, Lips 5977 k
% Time 703.000 ms, User 53 %, Lips 6915 k
% Time 766.000 ms, User 64 %, Lips 5339 k
true.
But this makes me ask, where would one see using for
example SWI-Prolog Engines for the actor model, so that it
becomes competitive to asyncio.Future? Any idea how to do it?
I guess asyncio.Future only uses a micro queue or something.
This would give the ISOMICRO profile of Web Prolog, a profile
that can run on small embedded devices single threaded.
The opposite of high performance computing (HPC).
Bye
P.S.: Here the source code, first what was used for validation:
classic ping pong with channels and with logging
:- ensure_loaded(library(util/tasks)).
% ping(+Integer, +Object, +Object)
ping(0, P, _) :-
send(P, finished),
write('Ping finished'), nl.
ping(N, P, Q) :- N > 0,
send(P, ping(Q)),
recv(Q, pong),
write('Ping received pong'), nl,
M is N-1,
ping(M, P, Q).
% pong(+Object)
pong(P) :-
recv(P, M),
(M = finished,
write('Pong finished'), nl;
M = ping(Q),
write('Pong received ping'), nl,
send(Q, pong),
pong(P)).
% pong(+Integer)
ping_pong(N) :-
chan(P),
chan(Q),
create_task(ping(N,P,Q),S),
create_task(pong(P),T),
task_join(S),
task_join(T).
And the validation output:
log of running N=3
?- ping_pong(3).
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Ping finished
Pong finished
true.
And what was used for benchmarking:
classic ping pong with channels and without logging
:- ensure_loaded(library(util/tasks)).
% ping(+Integer, +Object, +Object)
ping(0, P, _) :-
send(P, finished).
ping(N, P, Q) :- N > 0,
send(P, ping(Q)),
recv(Q, pong),
M is N-1,
ping(M, P, Q).
% pong(+Object)
pong(P) :-
recv(P, M),
(M = finished;
M = ping(Q),
send(Q, pong),
pong(P)).
% pong(+Integer)
ping_pong(N) :-
chan(P),
chan(Q),
create_task(ping(N,P,Q),S),
create_task(pong(P),T),
task_join(S),
task_join(T).
