Skip to content

Instantly share code, notes, and snippets.

@benaadams
Forked from abdullin/LICENSE
Last active February 15, 2018 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benaadams/a6f43fe96221384f2654c19673bb382e to your computer and use it in GitHub Desktop.
Save benaadams/a6f43fe96221384f2654c19673bb382e to your computer and use it in GitHub Desktop.
Naive ring benchmark in .NET Core using simulated actors

This is a naive (see for yourself!) implementation that explores the idea of simulating a ring of N actors that send the messages to each over M times.

Concept of the ring benchmark and simulated actors is taken from the gist by Preetam Jinka: https://gist.github.com/Preetam/98e80cd17ecb8748c72b

Given N=1000 and M=1000, the result on my machine is:

~$ dotnet run -c Release
00:00:00.0253974

This naive implementation is a start for building up a deterministic simulation of a cluster in a world full of failures. Another building block is the time simulation: https://github.com/abdullin/simcpu

Questions

  • How would you implement a ring benchmark in golang?
  • This .NET Core implementation is way faster than Erlang. What does Erlang spend time on?
  • Why is this implementation faster than FoundationDB Flow? What extra work could the Flow do?
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace SimRing {
class Program {
static void Main(string[] args) {
const int n = 1000;
const int m = 1000;
var actors = new List<Actor>();
var sim = new Sim();
for (int i = 0; i < n; i++) {
var next = (i + 1) % n;
actors.Add(new Actor(next, sim, m));
}
sim.Send(0, new {hello = "world"});
var watch = Stopwatch.StartNew();
while (sim.GetNextMessage(out var msg)) {
actors[msg.Recipient].HandleMessage(msg.Body);
}
Console.WriteLine(watch.Elapsed);
}
}
public class Actor {using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
namespace SimRing
{
class Program
{
static void Main(string[] args)
{
// warm up (Jit)
Execute();
// run
var elpased = Execute();
Console.WriteLine(elpased);
}
static TimeSpan Execute()
{
const int n = 1000;
const int m = 1000;
var actors = new List<Actor>();
var sim = new Sim();
for (int i = 0; i < n; i++)
{
var next = (i + 1) % n;
actors.Add(new Actor(next, sim, m));
}
sim.Send(0, new { hello = "world" });
var watch = Stopwatch.StartNew();
while (sim.GetNextMessage(out var msg))
{
actors[msg.Recipient].HandleMessage(msg.Body);
}
watch.Stop();
return watch.Elapsed;
}
}
public class Actor
{
readonly int NextActor;
int _counter;
readonly Sim _sim;
readonly int _m;
public Actor(int nextActor, Sim sim, int m)
{
NextActor = nextActor;
_sim = sim;
_m = m;
}
public void HandleMessage(object message)
{
_counter++;
if (_counter <= _m)
{
_sim.Send(NextActor, message);
}
}
}
public struct Message
{
public readonly int Recipient;
public readonly object Body;
public Message(int recipient, object body)
{
Recipient = recipient;
Body = body;
}
}
public sealed class Sim
{
readonly ConcurrentQueue<Message> _messages = new ConcurrentQueue<Message>();
public void Send(int recipient, object message)
{
_messages.Enqueue(new Message(recipient, message));
}
public bool GetNextMessage(out Message msg)
{
return _messages.TryDequeue(out msg);
}
}
}
readonly int NextActor;
int _counter;
readonly Sim _sim;
readonly int _m;
public Actor(int nextActor, Sim sim, int m) {
NextActor = nextActor;
_sim = sim;
_m = m;
}
public void HandleMessage(object message) {
_counter++;
if (_counter <= _m) {
_sim.Send(NextActor, message);
}
}
}
public struct Message {
public readonly int Recipient;
public readonly object Body;
public Message(int recipient, object body) {
Recipient = recipient;
Body = body;
}
}
public sealed class Sim {
readonly Queue<Message> _messages = new Queue<Message>();
public void Send(int recipient, object message) {
_messages.Enqueue(new Message(recipient, message));
;
}
public bool GetNextMessage(out Message msg) {
return _messages.TryDequeue(out msg);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment