Skip to content

Commit

Permalink
Merge branch 'v1.3' into Fix_Akka.MultiTestNodeRunner.Shared.Tests_#2828
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkatufus authored Jul 29, 2017
2 parents 4e6e05d + 05e1d77 commit 5111fd8
Show file tree
Hide file tree
Showing 17 changed files with 1,223 additions and 78 deletions.
7 changes: 5 additions & 2 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ Target "NBench" <| fun _ ->
| _ -> getAllPerfTestAssemblies()

let runNBench assembly =
let spec = getBuildParam "spec"
let include = getBuildParam "include"
let exclude = getBuildParam "exclude"
let teamcityStr = (getBuildParam "teamcity")
let enableTeamCity =
match teamcityStr with
Expand All @@ -262,6 +263,8 @@ Target "NBench" <| fun _ ->
|> append (sprintf "concurrent=\"%b\"" true)
|> append (sprintf "trace=\"%b\"" true)
|> append (sprintf "teamcity=\"%b\"" enableTeamCity)
|> appendIfNotNullOrEmpty include "include="
|> appendIfNotNullOrEmpty exclude "include="
|> toText

let result = ExecProcess(fun info ->
Expand Down Expand Up @@ -381,7 +384,7 @@ Target "DocFx" (fun _ ->

DocFx (fun p ->
{ p with
Timeout = TimeSpan.FromMinutes 5.0;
Timeout = TimeSpan.FromMinutes 30.0;
WorkingDirectory = docsPath;
DocFxJson = docsPath @@ "docfx.json" })
)
Expand Down
17 changes: 16 additions & 1 deletion src/Akka.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.15
VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmark", "Benchmark", "{73108242-625A-4D7B-AA09-63375DBAE464}"
EndProject
Expand Down Expand Up @@ -173,6 +173,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DistributedData.Lightn
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpawnBenchmark", "benchmark\SpawnBenchmark\SpawnBenchmark.csproj", "{DA4BDE1E-1ACA-482A-9329-952C3E36F97D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RemotePingPong", "benchmark\RemotePingPong\RemotePingPong.csproj", "{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -688,6 +690,18 @@ Global
{DA4BDE1E-1ACA-482A-9329-952C3E36F97D}.Release|x64.Build.0 = Release|Any CPU
{DA4BDE1E-1ACA-482A-9329-952C3E36F97D}.Release|x86.ActiveCfg = Release|Any CPU
{DA4BDE1E-1ACA-482A-9329-952C3E36F97D}.Release|x86.Build.0 = Release|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Debug|x64.ActiveCfg = Debug|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Debug|x64.Build.0 = Debug|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Debug|x86.ActiveCfg = Debug|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Debug|x86.Build.0 = Debug|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Release|Any CPU.Build.0 = Release|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Release|x64.ActiveCfg = Release|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Release|x64.Build.0 = Release|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Release|x86.ActiveCfg = Release|Any CPU
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -759,5 +773,6 @@ Global
{94C10096-C33E-404E-B0FB-F8535512A952} = {01167D3C-49C4-4CDE-9787-C176D139ACDD}
{99CCB7CA-E1EE-4497-BF52-2200A0EC5CB1} = {76F58DC4-19F1-43EF-A6E2-EC1CC8395AC5}
{DA4BDE1E-1ACA-482A-9329-952C3E36F97D} = {73108242-625A-4D7B-AA09-63375DBAE464}
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF} = {73108242-625A-4D7B-AA09-63375DBAE464}
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions src/benchmark/RemotePingPong/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
282 changes: 282 additions & 0 deletions src/benchmark/RemotePingPong/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="Akka.NET Project">
// Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2016 Akka.NET project <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Configuration;
using Akka.Util.Internal;

namespace RemotePingPong
{
public static class Messages
{
public class Msg { public override string ToString() { return "msg"; } }
public class Run { public override string ToString() { return "run"; } }
public class Started { public override string ToString() { return "started"; } }
}

internal class Program
{
public static uint CpuSpeed()
{
#if THREADS
var mo = new System.Management.ManagementObject("Win32_Processor.DeviceID='CPU0'");
var sp = (uint)(mo["CurrentClockSpeed"]);
mo.Dispose();
return sp;
#else
return 0;
#endif
}

public static Config CreateActorSystemConfig(string actorSystemName, string ipOrHostname, int port)
{
var baseConfig = ConfigurationFactory.ParseString(@"
akka {
actor.provider = remote
loglevel = ERROR
suppress-json-serializer-warning = on
log-dead-letters = off
remote {
log-remote-lifecycle-events = off
dot-netty.tcp {
port = 0
hostname = ""localhost""
}
}
");

var bindingConfig =
ConfigurationFactory.ParseString(@"akka.remote.dot-netty.tcp.hostname = """ + ipOrHostname + @"""")
.WithFallback(ConfigurationFactory.ParseString(@"akka.remote.dot-netty.tcp.port = " + port));

return bindingConfig.WithFallback(baseConfig);
}

private static void Main(params string[] args)
{
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
uint timesToRun;
if (args.Length == 0 || !uint.TryParse(args[0], out timesToRun))
{
timesToRun = 1u;
}

Start(timesToRun);
Console.ReadKey();
}

private static async void Start(uint timesToRun)
{
const long repeat = 10000L;

var processorCount = Environment.ProcessorCount;
if (processorCount == 0)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Failed to read processor count..");
return;
}

#if THREADS
int workerThreads;
int completionPortThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);

Console.WriteLine("Worker threads: {0}", workerThreads);
Console.WriteLine("OSVersion: {0}", Environment.OSVersion);
#endif
Console.WriteLine("ProcessorCount: {0}", processorCount);
Console.WriteLine("ClockSpeed: {0} MHZ", CpuSpeed());
Console.WriteLine("Actor Count: {0}", processorCount * 2);
Console.WriteLine("Messages sent/received per client: {0} ({0:0e0})", repeat*2);
Console.WriteLine("Is Server GC: {0}", GCSettings.IsServerGC);
Console.WriteLine();

//Print tables
Console.WriteLine("Num clients, Total [msg], Msgs/sec, Total [ms]");

for (var i = 0; i < timesToRun; i++)
{
var redCount = 0;
var bestThroughput = 0L;
foreach (var throughput in GetClientSettings())
{
var result1 = await Benchmark(throughput, repeat, bestThroughput, redCount);
bestThroughput = result1.Item2;
redCount = result1.Item3;
}
}

Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine("Done..");
}

public static IEnumerable<int> GetClientSettings()
{
yield return 1;
yield return 5;
yield return 10;
yield return 15;
yield return 20;
yield return 25;
yield return 30;
}

private static long GetTotalMessagesReceived(int numberOfClients, long numberOfRepeats)
{
return numberOfClients * numberOfRepeats * 2;
}

private static async Task<Tuple<bool, long, int>> Benchmark(int numberOfClients, long numberOfRepeats, long bestThroughput, int redCount)
{
var totalMessagesReceived = GetTotalMessagesReceived(numberOfClients, numberOfRepeats);
var system1 = ActorSystem.Create("SystemA", CreateActorSystemConfig("SystemA", "127.0.0.1", 0));

var system2 = ActorSystem.Create("SystemB", CreateActorSystemConfig("SystemB", "127.0.0.1", 0));

List<Task<long>> tasks = new List<Task<long>>();
List<IActorRef> receivers = new List<IActorRef>();

var canStart = system1.ActorOf(Props.Create(() => new AllStartedActor()), "canStart");

var system1Address = ((ExtendedActorSystem)system1).Provider.DefaultAddress;
var system2Address = ((ExtendedActorSystem)system2).Provider.DefaultAddress;

var echoProps = Props.Create(() => new EchoActor()).WithDeploy(new Deploy(new RemoteScope(system2Address)));

for (var i = 0; i < numberOfClients; i++)
{
var echo = system1.ActorOf(echoProps, "echo" + i);
var ts = new TaskCompletionSource<long>();
tasks.Add(ts.Task);
var receiver =
system1.ActorOf(
Props.Create(() => new BenchmarkActor(numberOfRepeats, ts, echo)),
"benchmark" + i);

receivers.Add(receiver);

canStart.Tell(echo);
canStart.Tell(receiver);
}

var rsp = await canStart.Ask(new AllStartedActor.AllStarted(), TimeSpan.FromSeconds(10));
var testReady = (bool)rsp;
if (!testReady)
{
throw new Exception("Received report that 1 or more remote actor is unable to begin the test. Aborting run.");
}

var sw = Stopwatch.StartNew();
receivers.ForEach(c =>
{
for (var i = 0; i < 50; i++) // prime the pump so EndpointWriters can take advantage of their batching model
c.Tell("hit");
});
var waiting = Task.WhenAll(tasks);
await Task.WhenAll(waiting);
sw.Stop();

// force clean termination
var termination = Task.WhenAll(new[] { system1.Terminate(), system2.Terminate() }).Wait(TimeSpan.FromSeconds(10));

var elapsedMilliseconds = sw.ElapsedMilliseconds;
long throughput = elapsedMilliseconds == 0 ? -1 : (long)Math.Ceiling((double)totalMessagesReceived / elapsedMilliseconds * 1000);
var foregroundColor = Console.ForegroundColor;
if (throughput >= bestThroughput)
{
Console.ForegroundColor = ConsoleColor.Green;
bestThroughput = throughput;
redCount = 0;
}
else
{
redCount++;
Console.ForegroundColor = ConsoleColor.Red;
}

Console.ForegroundColor = foregroundColor;
Console.WriteLine("{0,10},{1,8},{2,10},{3,11}", numberOfClients, totalMessagesReceived, throughput, sw.Elapsed.TotalMilliseconds.ToString("F2", CultureInfo.InvariantCulture));
return Tuple.Create(redCount <= 3, bestThroughput, redCount);
}

private class AllStartedActor : UntypedActor
{
public class AllStarted { }

private readonly HashSet<IActorRef> _actors = new HashSet<IActorRef>();
private int _correlationId = 0;

protected override void OnReceive(object message)
{
switch (message)
{
case IActorRef a:
_actors.Add(a);
break;
case AllStarted a:
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var s = Sender;
var count = _actors.Count;
var c = _correlationId++;
var t = Task.WhenAll(_actors.Select(
x => x.Ask<ActorIdentity>(new Identify(c), cts.Token)));
t.ContinueWith(tr =>
{
return tr.Result.Length == count && tr.Result.All(x => x.MessageId.Equals(c));
}, TaskContinuationOptions.OnlyOnRanToCompletion).PipeTo(s);
break;
}
}
}

private class EchoActor : UntypedActor
{
protected override void OnReceive(object message)
{
Sender.Tell(message);
}
}

private class BenchmarkActor : UntypedActor
{
private readonly long _maxExpectedMessages;
private readonly IActorRef _echo;
private long _currentMessages = 0;
private readonly TaskCompletionSource<long> _completion;

public BenchmarkActor(long maxExpectedMessages, TaskCompletionSource<long> completion, IActorRef echo)
{
_maxExpectedMessages = maxExpectedMessages;
_completion = completion;
_echo = echo;
}
protected override void OnReceive(object message)
{
if (_currentMessages < _maxExpectedMessages)
{
_currentMessages++;
_echo.Tell(message);
}
else
{
_completion.TrySetResult(_maxExpectedMessages);
}
}
}
}
}
9 changes: 9 additions & 0 deletions src/benchmark/RemotePingPong/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

Loading

0 comments on commit 5111fd8

Please sign in to comment.