Token Ring Election Benchmark
Workers forward tokens around a ring to measure message-passing performance. This historical benchmark demonstrates agent creation, message routing and a Java module shared by multiple agents. Despite its retained title, the code measures token passing and does not elect a leader.
Run the example
Use an ASTRA 2.6.1 project from the Quick Start. Save Worker.astra and Launcher.astra in src/main/astra/benchmarks/tokenring, and Timer.java in src/main/java/benchmarks/tokenring.
The original workload uses 500 workers and 500,000 forwarding steps per token. For an initial experiment, change WT to 5 and N to 100, then enter 1 token. The code is retained from the original guide and has not been validated against ASTRA 2.3.0.
Worker.astra
package benchmarks.tokenring;
agent Worker {
module Timer timer;
plan @message(inform, string sender, token(int I, 0)) {
timer.shutdown();
}
plan @message(inform, string sender, token(int I, int N)) : next(int X) {
send(inform, ""+X, token(I, N-1));
}
plan @message(inform, "main", init(int X)) {
+next(X);
}
}
Launcher.astra
package benchmarks.tokenring;
agent Launcher {
module Timer timer;
module Console console;
module System system;
plan +!main(list args) {
int WT = 500;
int N = 500000;
console.println("enter number of tokens: ");
console.readInt(int T);
console.println("enter scheduler pool size: ");
console.readInt(int size);
// Create the token ring
int i = 1;
while (i <= WT) {
system.createAgent(""+i, "benchmarks.tokenring.Worker");
send(inform, ""+i, init((i%WT)+1));
i = i + 1;
}
// Start the timer (configuring it for T tokens)
timer.startup(T);
// Send out the initial tokens
i = 1;
while (i <= T) {
send(inform, "" + (i * (WT/T)), token(i, N+1));
i = i + 1;
}
}
}
Timer.java
package benchmarks.tokenring;
import astra.core.Module;
public class Timer extends Module {
private static long startTime;
private static int T = 0;
@ACTION
public boolean startup(int t) {
startTime = System.currentTimeMillis();
T = t;
return true;
}
@ACTION
public boolean shutdown() {
if (--T == 0) {
long duration = System.currentTimeMillis() - startTime;
System.out.println("Duration: " + duration);
System.exit(0);
}
return true;
}
}
From the project folder, run:
mvn -Dastra.main=benchmarks.tokenring.Launcher
Enter the token count and the requested scheduler pool size when prompted. The current launcher reads the pool size but does not apply it. Use a positive token count no greater than WT that divides WT exactly; the initial destination calculation is unsuitable for other values.
Expected output
The launcher prompts for inputs, then the timer is intended to print a duration in milliseconds and stop the process:
[main] enter number of tokens:
1
[main] enter scheduler pool size:
1
Duration: <elapsed milliseconds>
The duration depends on the machine and workload. This is an illustrative transcript, not a measured result. The shared timer counter also needs synchronization before timings from concurrent token completions can be trusted.
How it works
The launcher names workers 1 through WT and tells each worker its successor, with the last pointing back to 1. It starts a shared timer and sends each initial token to a calculated position in the ring.
A worker receiving a token with a nonzero counter forwards it to its successor with the counter reduced by one. The zero-counter plan ends that token’s journey and calls Timer.shutdown(); its placement before the general forwarding plan is significant.
The timer’s static fields share the start time and outstanding-token count across module instances. When the count reaches zero, it prints the elapsed time and exits. The current unsynchronized decrement can lose updates when tokens finish concurrently.
Try a change
Start with one token and a small ring, then increase the forwarding count. Add a diagnostic message for each token’s completion. Before comparing multiple-token timings, address the timer-counter and launch-configuration issues recorded in BUGS-TO-FIX.md in the guide repository.
See Creating Multiple Agents, Agent Communication and Creating your own Actions.
References
[1] Cardoso, R. C., Zatelli, M.R., Hubner, J.F., Bordini, R. H., “Towards Benchmarking Actor- and Agent-Based Programming Languages”, Proceedings of the 2013 workshop on Programming based on actors, agents, and decentralized control, pp 115-126, ISBN: 978-1-4503-2602-5, 2013