AnyEvent-MP
view release on metacpan or search on metacpan
ports being the special case/exception, where transport errors cannot
occur.
=item * Erlang uses processes and a mailbox, AEMP does not queue.
Erlang uses processes that selectively receive messages out of order, and
therefore needs a queue. AEMP is event based, queuing messages would serve
no useful purpose. For the same reason the pattern-matching abilities
of AnyEvent::MP are more limited, as there is little need to be able to
filter messages without dequeuing them.
This is not a philosophical difference, but simply stems from AnyEvent::MP
being event-based, while Erlang is process-based.
You can have a look at L<Coro::MP> for a more Erlang-like process model on
top of AEMP and Coro threads.
=item * Erlang sends are synchronous, AEMP sends are asynchronous.
Sending messages in Erlang is synchronous and blocks the process until
a connection has been established and the message sent (and so does not
need a queue that can overflow). AEMP sends return immediately, connection
establishment is handled in the background.
=item * Erlang suffers from silent message loss, AEMP does not.
Erlang implements few guarantees on messages delivery - messages can get
lost without any of the processes realising it (i.e. you send messages a,
b, and c, and the other side only receives messages a and c).
AEMP guarantees (modulo hardware errors) correct ordering, and the
guarantee that after one message is lost, all following ones sent to the
same port are lost as well, until monitoring raises an error, so there are
no silent "holes" in the message sequence.
If you want your software to be very reliable, you have to cope with
corrupted and even out-of-order messages in both Erlang and AEMP. AEMP
simply tries to work better in common error cases, such as when a network
link goes down.
=item * Erlang can send messages to the wrong port, AEMP does not.
In Erlang it is quite likely that a node that restarts reuses an Erlang
process ID known to other nodes for a completely different process,
causing messages destined for that process to end up in an unrelated
process.
AEMP does not reuse port IDs, so old messages or old port IDs floating
around in the network will not be sent to an unrelated port.
=item * Erlang uses unprotected connections, AEMP uses secure
authentication and can use TLS.
AEMP can use a proven protocol - TLS - to protect connections and
securely authenticate nodes.
=item * The AEMP protocol is optimised for both text-based and binary
communications.
The AEMP protocol, unlike the Erlang protocol, supports both programming
language independent text-only protocols (good for debugging), and binary,
language-specific serialisers (e.g. Storable). By default, unless TLS is
used, the protocol is actually completely text-based.
It has also been carefully designed to be implementable in other languages
with a minimum of work while gracefully degrading functionality to make the
protocol simple.
=item * AEMP has more flexible monitoring options than Erlang.
In Erlang, you can chose to receive I<all> exit signals as messages or
I<none>, there is no in-between, so monitoring single Erlang processes is
difficult to implement.
Monitoring in AEMP is more flexible than in Erlang, as one can choose
between automatic kill, exit message or callback on a per-port basis.
=item * Erlang tries to hide remote/local connections, AEMP does not.
Monitoring in Erlang is not an indicator of process death/crashes, in the
same way as linking is (except linking is unreliable in Erlang).
In AEMP, you don't "look up" registered port names or send to named ports
that might or might not be persistent. Instead, you normally spawn a port
on the remote node. The init function monitors you, and you monitor the
remote port. Since both monitors are local to the node, they are much more
reliable (no need for C<spawn_link>).
This also saves round-trips and avoids sending messages to the wrong port
(hard to do in Erlang).
=back
=head1 RATIONALE
=over 4
=item Why strings for port and node IDs, why not objects?
We considered "objects", but found that the actual number of methods
that can be called are quite low. Since port and node IDs travel over
the network frequently, the serialising/deserialising would add lots of
overhead, as well as having to keep a proxy object everywhere.
Strings can easily be printed, easily serialised etc. and need no special
procedures to be "valid".
And as a result, a port with just a default receiver consists of a single
code reference stored in a global hash - it can't become much cheaper.
=item Why favour JSON, why not a real serialising format such as Storable?
In fact, any AnyEvent::MP node will happily accept Storable as framing
format, but currently there is no way to make a node use Storable by
default (although all nodes will accept it).
The default framing protocol is JSON because a) JSON::XS is many times
faster for small messages and b) most importantly, after years of
experience we found that object serialisation is causing more problems
than it solves: Just like function calls, objects simply do not travel
easily over the network, mostly because they will always be a copy, so you
( run in 0.703 second using v1.01-cache-2.11-cpan-39bf76dae61 )