-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple Counters #115
Comments
Here's your problem:
You need to declare a |
Hi,
is used in both methods but not |
Hi, Thanks |
@tigerclawn82 good feedback. Let me put an example on this thread real quick. |
public class TcpServerSocketChannelHorizontalScaleSpec
{
static TcpServerSocketChannelHorizontalScaleSpec()
{
// Disable the logging factory
LoggingFactory.DefaultFactory = new NoOpLoggerFactory();
}
private static readonly IPEndPoint TEST_ADDRESS = new IPEndPoint(IPAddress.IPv6Loopback, 0);
protected ClientBootstrap ClientBootstrap;
protected ServerBootstrap ServerBoostrap;
protected IEventLoopGroup ClientGroup;
protected IEventLoopGroup WorkerGroup;
protected IEventLoopGroup ServerGroup;
private const string ClientConnectCounterName = "connected clients";
private Counter _clientConnectedCounter;
private const string InboundThroughputCounterName = "inbound ops";
private Counter _inboundThroughputCounter;
private const string OutboundThroughputCounterName = "outbound ops";
private Counter _outboundThroughputCounter;
private const string ErrorCounterName = "exceptions caught";
private Counter _errorCounter;
private IChannel _serverChannel;
private ConcurrentBag<IChannel> _clientChannels;
private CancellationTokenSource _shutdownBenchmark;
protected readonly ManualResetEventSlim ResetEvent = new ManualResetEventSlim(false);
public const int IterationCount = 1; // these are LONG-running benchmarks. stick with a lower iteration count
// Sleep main thread, then start a new client every 30 ms
private static readonly TimeSpan SleepInterval = TimeSpan.FromMilliseconds(300);
/// <summary>
/// If it takes longer than <see cref="SaturationThreshold"/> to establish 10 connections, we're saturated.
///
/// End the stress test.
/// </summary>
private static readonly TimeSpan SaturationThreshold = TimeSpan.FromSeconds(15);
private IReadFinishedSignal _signal;
protected virtual IChannelHandler GetEncoder()
{
return new LengthFieldPrepender(4, false);
}
protected virtual IChannelHandler GetDecoder()
{
return new LengthFieldBasedFrameDecoder(Int32.MaxValue, 0, 4, 0, 4);
}
[PerfSetup]
public void SetUp(BenchmarkContext context)
{
ClientGroup = new MultithreadEventLoopGroup(Environment.ProcessorCount/2);
ServerGroup = new MultithreadEventLoopGroup(1);
WorkerGroup = new MultithreadEventLoopGroup(Environment.ProcessorCount/2);
_shutdownBenchmark = new CancellationTokenSource();
_clientChannels = new ConcurrentBag<IChannel>();
_inboundThroughputCounter = context.GetCounter(InboundThroughputCounterName);
_outboundThroughputCounter = context.GetCounter(OutboundThroughputCounterName);
_clientConnectedCounter = context.GetCounter(ClientConnectCounterName);
_errorCounter = context.GetCounter(ErrorCounterName);
_signal = new ManualResetEventSlimReadFinishedSignal(ResetEvent);
var sb = new ServerBootstrap().Group(ServerGroup, WorkerGroup).Channel<TcpServerSocketChannel>()
.ChildOption(ChannelOption.TcpNodelay, true)
.ChildHandler(new ActionChannelInitializer<TcpSocketChannel>(channel =>
{
channel.Pipeline.AddLast(GetEncoder())
.AddLast(GetDecoder())
.AddLast(new IntCodec(true))
.AddLast(new CounterHandlerInbound(_inboundThroughputCounter))
.AddLast(new CounterHandlerOutbound(_outboundThroughputCounter))
.AddLast(new ErrorCounterHandler(_errorCounter));
}));
ClientBootstrap = new ClientBootstrap().Group(ClientGroup)
.Option(ChannelOption.TcpNodelay, true)
.Channel<TcpSocketChannel>().Handler(new ActionChannelInitializer<TcpSocketChannel>(
channel =>
{
channel.Pipeline.AddLast(GetEncoder())
.AddLast(GetDecoder())
.AddLast(new IntCodec(true))
.AddLast(new CounterHandlerInbound(_inboundThroughputCounter))
.AddLast(new CounterHandlerOutbound(_outboundThroughputCounter))
.AddLast(new ErrorCounterHandler(_errorCounter));
}));
var token = _shutdownBenchmark.Token;
_eventLoop = () =>
{
while (!token.IsCancellationRequested)
{
foreach (var channel in _clientChannels)
{
// unrolling a loop
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.WriteAsync(ThreadLocalRandom.Current.Next());
channel.Flush();
}
// sleep for a tiny bit, then get going again
Thread.Sleep(40);
}
};
// start server
_serverChannel = sb.BindAsync(TEST_ADDRESS).Result;
// connect to server with 1 client initially
_clientChannels.Add(ClientBootstrap.ConnectAsync(_serverChannel.LocalAddress).Result);
}
private Action _eventLoop;
[PerfBenchmark(Description = "Measures how quickly and with how much GC overhead a TcpSocketChannel --> TcpServerSocketChannel connection can decode / encode realistic messages",
NumberOfIterations = IterationCount, RunMode = RunMode.Iterations)]
[CounterMeasurement(InboundThroughputCounterName)]
[CounterMeasurement(OutboundThroughputCounterName)]
[CounterMeasurement(ClientConnectCounterName)]
[CounterMeasurement(ErrorCounterName)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
[MemoryMeasurement(MemoryMetric.TotalBytesAllocated)]
public void TcpServerSocketChannel_horizontal_scale_stress_test(BenchmarkContext context)
{
_clientConnectedCounter.Increment(); // for the initial client
var totalRunSeconds = TimeSpan.FromSeconds(ThreadLocalRandom.Current.Next(180, 360)); // 3-6 minutes
Console.WriteLine("Running benchmark for {0} minutes", totalRunSeconds.TotalMinutes);
var deadline = new PreciseDeadline(totalRunSeconds);
var due = DateTime.Now + totalRunSeconds;
var lastMeasure = due;
var task = Task.Factory.StartNew(_eventLoop); // start writing
var runCount = 1;
while (!deadline.IsOverdue)
{
// add a new client
_clientChannels.Add(ClientBootstrap.ConnectAsync(_serverChannel.LocalAddress).Result);
_clientConnectedCounter.Increment();
Thread.Sleep(SleepInterval);
if (++runCount%10 == 0)
{
Console.WriteLine("{0} minutes remaining [{1} connections active].", (due - DateTime.Now).TotalMinutes, runCount);
var saturation = (DateTime.Now - lastMeasure);
if (saturation > SaturationThreshold)
{
Console.WriteLine("Took {0} to create 10 connections; exceeded pre-defined saturation threshold of {1}. Ending stress test.", saturation, SaturationThreshold);
break;
}
lastMeasure = DateTime.Now;
}
}
_shutdownBenchmark.Cancel();
}
[PerfCleanup]
public void TearDown()
{
_eventLoop = null;
var shutdownTasks = new List<Task>();
foreach (var channel in _clientChannels)
{
shutdownTasks.Add(channel.CloseAsync());
}
Task.WaitAll(shutdownTasks.ToArray());
CloseChannel(_serverChannel);
Task.WaitAll(ClientGroup.ShutdownGracefullyAsync(), ServerGroup.ShutdownGracefullyAsync(), WorkerGroup.ShutdownGracefullyAsync());
}
private static void CloseChannel(IChannel cc)
{
cc?.CloseAsync().Wait();
}
} Used 4 counters at once there |
Hi, |
Multiple test methods: /// <summary>
/// Performance specifications for <see cref="ActorPath" />
/// </summary>
public class ActorPathSpec
{
private const string ParseThroughputCounterName = "ParseOp";
private const double MinimumAcceptableOperationsPerSecond = 1000000.0d; //million op / second
private static readonly RootActorPath RootAddress = new RootActorPath(Address.AllSystems);
private Counter _parseThroughput;
[PerfSetup]
public void Setup(BenchmarkContext context)
{
_parseThroughput = context.GetCounter(ParseThroughputCounterName);
}
[PerfBenchmark(Description = "Tests how quickly ActorPath.Parse can run on a LOCAL actor path",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void Parse_local_throughput(BenchmarkContext context)
{
ActorPath.Parse("akka://Sys/user/foo");
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how quickly ActorPath.Parse can run on a REMOTE actor path",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void Parse_remote_throughput(BenchmarkContext context)
{
ActorPath.Parse("akka.tcp://Sys@localhost:9091/user/foo");
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how quickly ActorPath.TryParse can run on a LOCAL actor path",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void TryParse_local_throughput(BenchmarkContext context)
{
ActorPath target;
ActorPath.TryParse("akka://Sys/user/foo", out target);
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how quickly ActorPath.TryParse can run on a REMOTE actor path",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void TryParse_remote_throughput(BenchmarkContext context)
{
ActorPath target;
ActorPath.TryParse("akka.tcp://Sys@localhost:9091/user/foo", out target);
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how quickly ActorPath.TryParseAddress can run on a LOCAL address",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan,
MinimumAcceptableOperationsPerSecond)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void TryParse_address_local_throughput(BenchmarkContext context)
{
Address target;
ActorPath.TryParseAddress("akka://Sys/user/foo", out target);
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how quickly ActorPath.TryParseAddress can run on a REMOTE address",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void TryParse_address_remote_throughput(BenchmarkContext context)
{
Address target;
ActorPath.TryParseAddress("akka.tcp://Sys@locahost:9101/user/foo", out target);
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how quickly a single ActorPath '/' operation can run",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void ActorPath1_concatenate_throughput(BenchmarkContext context)
{
var newPath = RootAddress/"user";
_parseThroughput.Increment();
}
[PerfBenchmark(
Description =
"Tests how quickly a two immediate ActorPath '/' operations can run - much closer to how this method works in the real world",
RunMode = RunMode.Throughput, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterThroughputAssertion(ParseThroughputCounterName, MustBe.GreaterThan, MinimumAcceptableOperationsPerSecond
)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void ActorPath2_concatenate_throughput(BenchmarkContext context)
{
var newPath = RootAddress/"user"/"foo";
_parseThroughput.Increment();
}
[PerfBenchmark(Description = "Tests how much memory 100,000 ActorPath instances consume",
RunMode = RunMode.Iterations, NumberOfIterations = 13, RunTimeMilliseconds = 1000,
TestMode = TestMode.Measurement)]
[CounterMeasurement(ParseThroughputCounterName)]
[MemoryMeasurement(MemoryMetric.TotalBytesAllocated)]
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
public void Memory_footprint(BenchmarkContext context)
{
var actorPaths = new ActorPath[100000];
for (var i = 0; i < 100000;)
{
actorPaths[i] = new RootActorPath(Address.AllSystems);
++i;
_parseThroughput.Increment();
}
}
} |
Sorry, took me a bit longer to grab the second one - had to open a different project up :p |
Hi,
used
used |
@tigerclawn82, ah, in that case you just need to make sure that you assign |
Hi,
Yeah, right now i have created separated classes per method but it seems overkill. But, thanks for your instant support 👍 |
@tigerclawn82 You're welcome! In a future release we're going to be adding something similar to XUnit Theories which might be able to help reduce the amount of code you have to write to do this. |
I will try to directly get counters in perf methods rather |
Hi, tried getting counter directly via |
Hi,
I have created multiple Perf Methods in single POCO. I am getting following output in console which have exceptions
I have used following code, please help if there is any issue in my setup or if i am missing something
Any help would be appreciated, Thanks
The text was updated successfully, but these errors were encountered: