2021-05-10 09:21:52 +00:00
|
|
|
# A surprisingly fast, surprisingly simple Actor library for Java
|
2021-05-10 09:13:23 +00:00
|
|
|
|
|
|
|
As part of my research work on
|
|
|
|
[Syndicate](https://syndicate-lang.org), in 2020 I built this simple
|
|
|
|
Actor library in and for Java.
|
|
|
|
|
|
|
|
It's a hybrid of Erlang-style and E-style Actor models: Erlang-style
|
|
|
|
in that it includes monitors and links, and E-style in that it peers
|
|
|
|
denote targets for messages via references to individual *objects*
|
|
|
|
with an actor. Actors are thus similar to E's *vats*.
|
|
|
|
|
|
|
|
So far, I've limited myself to implementing a straightforward Actor
|
|
|
|
system, not including Dataspace or Syndicate primitives.
|
|
|
|
|
2021-05-12 13:47:49 +00:00
|
|
|
## Quickstart
|
|
|
|
|
|
|
|
git clone https://git.syndicate-lang.org/syndicate-lang/syndicate-java
|
|
|
|
ant jar
|
|
|
|
|
|
|
|
Then, if you'd like to run the simple million-actor/200-message
|
|
|
|
benchmark discussed below, run `make ziprun`.
|
|
|
|
|
2021-05-10 09:21:52 +00:00
|
|
|
## Surprisingly fast
|
|
|
|
|
2021-05-10 09:13:23 +00:00
|
|
|
It's quite interesting all by itself, though: it's *very* fast and
|
|
|
|
able to use all the cores in a machine very effectively. For example:
|
|
|
|
|
|
|
|
$ java ... ...example2.Main 1000000 200
|
|
|
|
2021-05-10 11:02:35.087 INFO Actor(1) Available processors: 48
|
|
|
|
2021-05-10 11:02:38.573 INFO Actor(1) Start
|
|
|
|
2021-05-10 11:02:44.161 INFO Actor(1) Stop after 200000000 messages; 4.8 seconds, 41999160.0 Hz
|
|
|
|
|
|
|
|
That little benchmark has one million actors, each sending 200
|
|
|
|
messages to its neighbour in a ring, on my AMD 48-core machine. The
|
|
|
|
whole workload, 200 million messages, is delivered in under 5 seconds;
|
|
|
|
or, about 40 million messages per second. I was surprised that such a
|
|
|
|
simple system was able to perform so well.
|
|
|
|
|
|
|
|
Here's that same benchmark run on a single core:
|
|
|
|
|
|
|
|
$ taskset -c 0 java ... ...example2.Main 1000000 200
|
|
|
|
2021-05-10 11:07:42.104 INFO Actor(1) Available processors: 1
|
|
|
|
2021-05-10 11:07:47.826 INFO Actor(1) Start
|
|
|
|
2021-05-10 11:08:52.078 INFO Actor(1) Stop after 200000000 messages; 63.5 seconds, 3149903.9 Hz
|
|
|
|
|
|
|
|
That's just over 3 million messages per second on a single core. Neat, huh?
|
|
|
|
|
2021-05-10 09:21:52 +00:00
|
|
|
## Surprisingly simple
|
|
|
|
|
|
|
|
It's also only ~730 lines of code:
|
|
|
|
|
|
|
|
```
|
|
|
|
~/src/syndicate-java$ cloc src/main/java/
|
|
|
|
12 text files.
|
|
|
|
12 unique files.
|
|
|
|
0 files ignored.
|
|
|
|
|
|
|
|
github.com/AlDanial/cloc v 1.86 T=0.01 s (965.7 files/s, 69128.5 lines/s)
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
Language files blank comment code
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
Java 12 126 6 727
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
SUM: 12 126 6 727
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
```
|
|
|
|
|
|
|
|
## Next steps
|
|
|
|
|
2021-05-10 09:13:23 +00:00
|
|
|
Next steps are to implement proper Dataspace model entities, with
|
|
|
|
assertions and facets etc., and then build an actual Dataspace to go
|
|
|
|
with it. I'll be trying to reuse as much of this implementation style
|
|
|
|
as possible since it performs so well.
|