benchmark prototype

pull/11272/head
Jan Tattermusch 8 years ago
parent 7cc83c8cd5
commit e58842f33a
  1. 7
      src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
  2. 10
      src/csharp/Grpc.Microbenchmarks/Program.cs
  3. 106
      src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs
  4. 79
      src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs

@ -52,6 +52,7 @@ namespace Grpc.Core.Internal
readonly GrpcEnvironment environment; readonly GrpcEnvironment environment;
readonly ConcurrentDictionary<IntPtr, OpCompletionDelegate> dict = new ConcurrentDictionary<IntPtr, OpCompletionDelegate>(new IntPtrComparer()); readonly ConcurrentDictionary<IntPtr, OpCompletionDelegate> dict = new ConcurrentDictionary<IntPtr, OpCompletionDelegate>(new IntPtrComparer());
IntPtr lastRegisteredKey;
public CompletionRegistry(GrpcEnvironment environment) public CompletionRegistry(GrpcEnvironment environment)
{ {
@ -62,6 +63,7 @@ namespace Grpc.Core.Internal
{ {
environment.DebugStats.PendingBatchCompletions.Increment(); environment.DebugStats.PendingBatchCompletions.Increment();
GrpcPreconditions.CheckState(dict.TryAdd(key, callback)); GrpcPreconditions.CheckState(dict.TryAdd(key, callback));
this.lastRegisteredKey = key;
} }
public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback) public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback)
@ -84,6 +86,11 @@ namespace Grpc.Core.Internal
return value; return value;
} }
public IntPtr LastRegisteredKey
{
get { return this.lastRegisteredKey; }
}
private static void HandleBatchCompletion(bool success, BatchContextSafeHandle ctx, BatchCompletionDelegate callback) private static void HandleBatchCompletion(bool success, BatchContextSafeHandle ctx, BatchCompletionDelegate callback)
{ {
try try

@ -32,6 +32,8 @@
#endregion #endregion
using System; using System;
using Grpc.Core;
using Grpc.Core.Internal;
namespace Grpc.Microbenchmarks namespace Grpc.Microbenchmarks
{ {
@ -39,7 +41,13 @@ namespace Grpc.Microbenchmarks
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("Helloworld"); var benchmark = new SendMessageBenchmark();
benchmark.Init();
foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12})
{
benchmark.Run(threadCount, 4 * 1000 * 1000, 0);
}
benchmark.Cleanup();
} }
} }
} }

@ -0,0 +1,106 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Threading;
using Grpc.Core;
using Grpc.Core.Internal;
using System.Collections.Generic;
using System.Diagnostics;
namespace Grpc.Microbenchmarks
{
public class SendMessageBenchmark
{
static readonly NativeMethods Native = NativeMethods.Get();
GrpcEnvironment environment;
public void Init()
{
Native.grpcsharp_test_override_method("grpcsharp_call_start_batch", "nop");
environment = GrpcEnvironment.AddRef();
}
public void Cleanup()
{
GrpcEnvironment.ReleaseAsync().Wait();
// TODO(jtattermusch): track GC stats
}
public void Run(int threadCount, int iterations, int payloadSize)
{
Console.WriteLine(string.Format("SendMessageBenchmark: threads={0}, iterations={1}, payloadSize={2}", threadCount, iterations, payloadSize));
var threadedBenchmark = new ThreadedBenchmark(threadCount, () => ThreadBody(iterations, payloadSize));
threadedBenchmark.Run();
}
private void ThreadBody(int iterations, int payloadSize)
{
// TODO(jtattermusch): parametrize by number of pending completions.
// TODO(jtattermusch): parametrize by cached/non-cached BatchContextSafeHandle
var completionRegistry = new CompletionRegistry(environment);
var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry);
var call = CreateFakeCall(cq);
var sendCompletionHandler = new SendCompletionHandler((success) => { });
var payload = new byte[payloadSize];
var writeFlags = default(WriteFlags);
var stopwatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
call.StartSendMessage(sendCompletionHandler, payload, writeFlags, false);
var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey);
callback();
}
stopwatch.Stop();
Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds);
cq.Dispose();
}
private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq)
{
var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq);
bool success = false;
while (!success)
{
// avoid calling destroy on a nonexistent grpc_call pointer
call.DangerousAddRef(ref success);
}
return call;
}
}
}

@ -0,0 +1,79 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Threading;
using Grpc.Core;
using Grpc.Core.Internal;
using System.Collections.Generic;
using System.Diagnostics;
namespace Grpc.Microbenchmarks
{
public class ThreadedBenchmark
{
List<ThreadStart> runners;
public ThreadedBenchmark(IEnumerable<ThreadStart> runners)
{
this.runners = new List<ThreadStart>(runners);
}
public ThreadedBenchmark(int threadCount, Action threadBody)
{
this.runners = new List<ThreadStart>();
for (int i = 0; i < threadCount; i++)
{
this.runners.Add(new ThreadStart(() => threadBody()));
}
}
public void Run()
{
Console.WriteLine("Running threads.");
var threads = new List<Thread>();
for (int i = 0; i < runners.Count; i++)
{
var thread = new Thread(runners[i]);
thread.Start();
threads.Add(thread);
}
foreach (var thread in threads)
{
thread.Join();
}
Console.WriteLine("All threads finished.");
}
}
}
Loading…
Cancel
Save