Skip to content

Instantly share code, notes, and snippets.

@abdullin
Last active July 10, 2020 21:31
Show Gist options
  • Save abdullin/af7c9b7fd4aa58cadcc346c8e194d9ab to your computer and use it in GitHub Desktop.
Save abdullin/af7c9b7fd4aa58cadcc346c8e194d9ab 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:

/usr/local/share/dotnet/dotnet /Users/rinat/proj/core/SimRing/bin/Release/netcoreapp2.0/SimRing.dll
00:00:00.0260680

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?

I want to learn more! What is next?

Next, we'll plug into .NET Core async/await to simulate processes running in parallel. Check it out.

MIT License 2018 Rinat Abdullin
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 {
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