You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2015/10/02 10:37:30 UTC
[2/2] ignite git commit: IGNITE-1570: Moved local benchmarks project
from GG to Ignite.
IGNITE-1570: Moved local benchmarks project from GG to Ignite.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3852b0b6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3852b0b6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3852b0b6
Branch: refs/heads/ignite-1282
Commit: 3852b0b65fdcfeedd785405650f522e4b31865ff
Parents: c2a1631
Author: Pavel Tupitsyn <pt...@gridgain.com>
Authored: Fri Oct 2 11:38:11 2015 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Fri Oct 2 11:38:11 2015 +0300
----------------------------------------------------------------------
.../Apache.Ignite.Benchmarks.csproj | 83 ++
.../dotnet/Apache.Ignite.Benchmarks/App.config | 24 +
.../Apache.Ignite.Benchmarks/BenchmarkBase.cs | 931 +++++++++++++++++++
.../BenchmarkOperationDescriptor.cs | 68 ++
.../Apache.Ignite.Benchmarks/BenchmarkRunner.cs | 94 ++
.../Apache.Ignite.Benchmarks/BenchmarkState.cs | 106 +++
.../Apache.Ignite.Benchmarks/BenchmarkUtils.cs | 236 +++++
.../Config/benchmark.xml | 57 ++
.../Interop/ClosureBenchmark.cs | 66 ++
.../Interop/GetAsyncBenchmark.cs | 66 ++
.../Interop/GetBenchmark.cs | 62 ++
.../Interop/PlatformBenchmarkBase.cs | 122 +++
.../Interop/PutAsyncBenchmark.cs | 60 ++
.../Interop/PutBenchmark.cs | 58 ++
.../Interop/TaskBenchmark.cs | 100 ++
.../Interop/TxBenchmark.cs | 65 ++
.../Apache.Ignite.Benchmarks/Model/Address.cs | 80 ++
.../Apache.Ignite.Benchmarks/Model/Company.cs | 89 ++
.../Model/Department.cs | 40 +
.../Apache.Ignite.Benchmarks/Model/Employee.cs | 136 +++
.../Apache.Ignite.Benchmarks/Model/Sex.cs | 31 +
.../Portable/PortableWriteBenchmark.cs | 83 ++
.../Properties/AssemblyInfo.cs | 35 +
.../Result/BenchmarkConsoleResultWriter.cs | 68 ++
.../Result/BenchmarkFileResultWriter.cs | 323 +++++++
.../Result/IBenchmarkResultWriter.cs | 55 ++
.../Compute/ComputeApiTest.cs | 3 +-
.../Examples/PathUtil.cs | 2 +-
.../IgniteManagerTest.cs | 11 +-
.../Process/IgniteProcess.cs | 7 +-
.../Apache.Ignite.Core.Tests/TestUtils.cs | 3 +-
.../Apache.Ignite.Core.csproj | 2 +
.../Apache.Ignite.Core/Impl/Common/Classpath.cs | 159 ++++
.../Impl/Common/IgniteHome.cs | 97 ++
.../Apache.Ignite.Core/Impl/IgniteManager.cs | 206 +---
.../Properties/AssemblyInfo.cs | 1 +
modules/platforms/dotnet/Apache.Ignite.sln | 10 +
37 files changed, 3425 insertions(+), 214 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj
new file mode 100644
index 0000000..19f2724
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Apache.Ignite.Benchmarks.csproj
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{8F507DBE-56F9-437F-82D4-74C02EC44E41}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Ignite.Benchmarks</RootNamespace>
+ <AssemblyName>Apache.Ignite.Benchmarks</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject>Apache.Ignite.Benchmarks.BenchmarkRunner</StartupObject>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <OutputPath>bin\x86\Release\</OutputPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <OutputPath>bin\x64\Release\</OutputPath>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BenchmarkBase.cs" />
+ <Compile Include="BenchmarkOperationDescriptor.cs" />
+ <Compile Include="BenchmarkRunner.cs" />
+ <Compile Include="BenchmarkState.cs" />
+ <Compile Include="BenchmarkUtils.cs" />
+ <Compile Include="Interop\PlatformBenchmarkBase.cs" />
+ <Compile Include="Interop\ClosureBenchmark.cs" />
+ <Compile Include="Interop\GetAsyncBenchmark.cs" />
+ <Compile Include="Interop\GetBenchmark.cs" />
+ <Compile Include="Interop\PutAsyncBenchmark.cs" />
+ <Compile Include="Interop\PutBenchmark.cs" />
+ <Compile Include="Interop\TaskBenchmark.cs" />
+ <Compile Include="Interop\TxBenchmark.cs" />
+ <Compile Include="Model\Address.cs" />
+ <Compile Include="Model\Company.cs" />
+ <Compile Include="Model\Department.cs" />
+ <Compile Include="Model\Employee.cs" />
+ <Compile Include="Model\Sex.cs" />
+ <Compile Include="Portable\PortableWriteBenchmark.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Result\BenchmarkConsoleResultWriter.cs" />
+ <Compile Include="Result\BenchmarkFileResultWriter.cs" />
+ <Compile Include="Result\IBenchmarkResultWriter.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Apache.Ignite.Core\Apache.Ignite.Core.csproj">
+ <Project>{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}</Project>
+ <Name>Apache.Ignite.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ <None Include="Config\benchmark.xml" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/App.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/App.config b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/App.config
new file mode 100644
index 0000000..f21105a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/App.config
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<configuration>
+ <runtime>
+ <gcServer enabled="true"/>
+ </runtime>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkBase.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkBase.cs
new file mode 100644
index 0000000..8921aef
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkBase.cs
@@ -0,0 +1,931 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
+ using System.Text;
+ using System.Threading;
+ using Apache.Ignite.Benchmarks.Result;
+
+ /// <summary>
+ /// Benchmark base class.
+ /// </summary>
+ internal abstract class BenchmarkBase
+ {
+ /** Result writer type: console. */
+ private const string ResultWriterConsole = "console";
+
+ /** Result writer type: file. */
+ private const string ResultWriterFile = "file";
+
+ /** Default duration. */
+ private const int DefaultDuration = 60;
+
+ /** Default maximum errors count. */
+ private const int DefaultMaxErrors = 100;
+
+ /** Default percentile result buckets count. */
+ private const int DEfaultResultBucketCount = 10000;
+
+ /** Default percentile result bucket interval. */
+ private const int DefaultResultBucketInterval = 100;
+
+ /** Default batch size. */
+ private const int DefaultBatchSize = 1;
+
+ /** Default result wrier. */
+ private const string DefaultResultWriter = ResultWriterConsole;
+
+ /** Start flag. */
+ private volatile bool _start;
+
+ /** Stop flag. */
+ private volatile bool _stop;
+
+ /** Warmup flag. */
+ private volatile bool _warmup = true;
+
+ /** Ready threads. */
+ private int _readyThreads;
+
+ /** Finished threads. */
+ private volatile int _finishedThreads;
+
+ /** Descriptors. */
+ private volatile ICollection<BenchmarkOperationDescriptor> _descs;
+
+ /** Benchmark tasks. */
+ private volatile ICollection<BenchmarkTask> _tasks;
+
+ /** Percentile results. */
+ private volatile IDictionary<string, long[]> _percentiles;
+
+ /** Currently completed operations. */
+ private long _curOps;
+
+ /** Error count. */
+ private long _errorCount;
+
+ /** Watches to count total execution time. */
+ private readonly Stopwatch _totalWatch = new Stopwatch();
+
+ /** Warmup barrier. */
+ private Barrier _barrier;
+
+ /** Benchmark result writer. */
+ private IBenchmarkResultWriter _writer;
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ protected BenchmarkBase()
+ {
+ Duration = DefaultDuration;
+ MaxErrors = DefaultMaxErrors;
+ ResultBucketCount = DEfaultResultBucketCount;
+ ResultBucketInterval = DefaultResultBucketInterval;
+ BatchSize = DefaultBatchSize;
+ ResultWriter = DefaultResultWriter;
+ }
+
+ /// <summary>
+ /// Run the benchmark.
+ /// </summary>
+ public void Run()
+ {
+ PrintDebug("Started benchmark: " + this);
+
+ ValidateArguments();
+
+ if (ResultWriter.ToLower().Equals(ResultWriterConsole))
+ _writer = new BenchmarkConsoleResultWriter();
+ else
+ _writer = new BenchmarkFileResultWriter();
+
+ OnStarted();
+
+ PrintDebug("Benchmark setup finished.");
+
+ try
+ {
+ _descs = new List<BenchmarkOperationDescriptor>();
+
+ GetDescriptors(_descs);
+
+ if (_descs.Count == 0)
+ throw new Exception("No tasks provided for benchmark.");
+
+ // Initialize writer.
+ var opNames = new List<string>(_descs.Select(desc => desc.Name));
+
+ PrintDebug(() =>
+ {
+ var sb = new StringBuilder("Operations: ");
+
+ foreach (var opName in opNames)
+ sb.Append(opName).Append(" ");
+
+ return sb.ToString();
+ });
+
+ _writer.Initialize(this, opNames);
+
+ PrintDebug("Initialized result writer.");
+
+ // Start worker threads.
+ _tasks = new List<BenchmarkTask>(Threads);
+
+ PrintDebug("Starting worker threads: " + Threads);
+
+ for (var i = 0; i < Threads; i++)
+ {
+ var task = new BenchmarkTask(this, _descs);
+
+ _tasks.Add(task);
+
+ new Thread(task.Run).Start();
+ }
+
+ PrintDebug("Waiting worker threads to start: " + Threads);
+
+ // Await for all threads to start in spin loop.
+ while (Thread.VolatileRead(ref _readyThreads) < Threads)
+ Thread.Sleep(10);
+
+ PrintDebug("Worker threads started: " + Threads);
+
+ // Start throughput writer thread.
+ var writerThread = new Thread(new ThroughputTask(this).Run) {IsBackground = true};
+
+ writerThread.Start();
+
+ PrintDebug("Started throughput writer thread.");
+
+ // Start warmup thread if needed.
+ if (Warmup > 0)
+ {
+ var thread = new Thread(new WarmupTask(this, Warmup).Run) {IsBackground = true};
+
+ thread.Start();
+
+ PrintDebug("Started warmup timeout thread: " + Warmup);
+ }
+ else
+ _warmup = false;
+
+ _barrier = new Barrier(Threads, b =>
+ {
+ Console.WriteLine("Warmup finished.");
+
+ _totalWatch.Start();
+ });
+
+ // Start timeout thread if needed.
+ if (Duration > 0)
+ {
+ if (Operations > 0)
+ PrintDebug("Duration argument is ignored because operations number is set: " +
+ Operations);
+ else
+ {
+ var thread = new Thread(new TimeoutTask(this, Warmup + Duration).Run) {IsBackground = true};
+
+ thread.Start();
+
+ PrintDebug("Started duration timeout thread: " + Duration);
+ }
+ }
+
+ // Let workers start execution.
+ _start = true;
+
+ // Await workers completion.
+ PrintDebug("Awaiting worker threads completion.");
+
+ Monitor.Enter(this);
+
+ try
+ {
+ while (_finishedThreads < Threads)
+ Monitor.Wait(this);
+ }
+ finally
+ {
+ Monitor.Exit(this);
+ }
+
+ PrintDebug("Worker threads completed.");
+ }
+ finally
+ {
+ OnFinished();
+
+ _totalWatch.Stop();
+
+ PrintDebug("Tear down invoked.");
+
+ if (PrintThroughputInfo())
+ {
+ var avgThroughput = _totalWatch.ElapsedMilliseconds == 0
+ ? 0
+ : _curOps*1000/_totalWatch.ElapsedMilliseconds;
+
+ var avgLatency = _curOps == 0
+ ? 0
+ : (double) _totalWatch.ElapsedMilliseconds*Threads/_curOps;
+
+ Console.WriteLine("Finishing benchmark [name=" + GetType().Name +
+ ", time=" + _totalWatch.ElapsedMilliseconds +
+ "ms, ops=" + _curOps +
+ ", threads=" + Threads +
+ ", avgThroughput=" + avgThroughput +
+ ", avgLatency=" + string.Format("{0:0.000}ms", avgLatency) + ']');
+ }
+ else
+ {
+ Console.WriteLine("Finishing benchmark [name=" + GetType().Name +
+ ", time=" + _totalWatch.ElapsedMilliseconds +
+ "ms, ops=" + Operations +
+ ", threads=" + Threads + ']');
+ }
+ }
+
+ _percentiles = new Dictionary<string, long[]>(_descs.Count);
+
+ foreach (var desc in _descs)
+ _percentiles[desc.Name] = new long[ResultBucketCount];
+
+ foreach (var task in _tasks)
+ task.CollectPercentiles(_percentiles);
+
+ foreach (var percentile in _percentiles)
+ _writer.WritePercentiles(percentile.Key, ResultBucketInterval, percentile.Value);
+
+ _writer.Commit();
+
+ PrintDebug("Results committed to output writer.");
+ }
+
+ /// <summary>
+ /// Consumes passed argument.
+ /// </summary>
+ /// <param name="name">Argument name.</param>
+ /// <param name="val">Value.</param>
+ /// <returns>True if argument was consumed.</returns>
+ public void Configure(string name, string val)
+ {
+ var prop = BenchmarkUtils.GetProperty(this, name);
+
+ if (prop != null)
+ BenchmarkUtils.SetProperty(this, prop, val);
+ }
+
+ /// <summary>
+ /// Start callback.
+ /// </summary>
+ protected virtual void OnStarted()
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Warmup finished callback. Executed by each worker thread once.
+ /// </summary>
+ protected virtual void OnWarmupFinished()
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Batch execution started callback.
+ /// </summary>
+ /// <param name="state">State.</param>
+ protected virtual void OnBatchStarted(BenchmarkState state)
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Batch execution finished callback.
+ /// </summary>
+ /// <param name="state">State.</param>
+ /// <param name="duration">Duration.</param>
+ /// <returns>True if this result must be counted.</returns>
+ protected virtual bool OnBatchFinished(BenchmarkState state, long duration)
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// Benchmarh finished callback.
+ /// </summary>
+ protected virtual void OnFinished()
+ {
+ // No-op.
+ }
+
+ /// <returns>Flag indicating whether benchmark should print throughput information.</returns>
+ protected virtual bool PrintThroughputInfo()
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// Internal arguments validation routine.
+ /// </summary>
+ /// <returns>True if base class must validate common arguments, false otherwise.</returns>
+ protected virtual bool ValidateArgumentsEx()
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// Print debug to console.
+ /// </summary>
+ /// <param name="msg">Message</param>
+ protected void PrintDebug(string msg)
+ {
+ if (Debug)
+ Console.WriteLine("[DEBUG] " + Thread.CurrentThread.ManagedThreadId + ": " + msg);
+ }
+
+ /// <summary>
+ /// Print debug to console.
+ /// </summary>
+ /// <param name="msgFunc">Message delegate.</param>
+ protected void PrintDebug(Func<string> msgFunc)
+ {
+ if (Debug)
+ PrintDebug(msgFunc.Invoke());
+ }
+
+ /// <summary>
+ /// Add operation descriptors.
+ /// </summary>
+ /// <param name="descs">Collection where operation descriptors must be added.</param>
+ protected abstract void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs);
+
+ /// <summary>
+ /// Invoked when single thread is ready to actual execution.
+ /// </summary>
+ private void OnThreadReady()
+ {
+ Interlocked.Increment(ref _readyThreads);
+ }
+
+ /// <summary>
+ /// Invoked when single thread finished execution.
+ /// </summary>
+ private void OnThreadFinished()
+ {
+ Monitor.Enter(this);
+
+ try
+ {
+ _finishedThreads++;
+
+ Monitor.PulseAll(this);
+ }
+ finally
+ {
+ Monitor.Exit(this);
+ }
+
+ PrintDebug("Worker thread finished.");
+ }
+
+ /// <summary>
+ /// Validate arguments.
+ /// </summary>
+ private void ValidateArguments()
+ {
+ if (ValidateArgumentsEx())
+ {
+ if (Threads <= 0)
+ throw new Exception("Threads must be positive: " + Threads);
+
+ if (Warmup < 0)
+ throw new Exception("Warmup cannot be negative: " + Warmup);
+
+ if (Duration < 0)
+ throw new Exception("Duration cannot be negative: " + Duration);
+
+ if (BatchSize <= 0)
+ throw new Exception("BatchSize must be positive: " + BatchSize);
+
+ if (MaxErrors < 0)
+ throw new Exception("MaxErrors cannot be negative: " + MaxErrors);
+
+ if (ResultWriter == null || !ResultWriter.ToLower().Equals(ResultWriterConsole)
+ && !ResultWriter.ToLower().Equals(ResultWriterFile))
+ throw new Exception("Invalid ResultWriter: " + ResultWriter);
+
+ if (ResultWriter.ToLower().Equals(ResultWriterFile) && ResultFolder == null)
+ throw new Exception("ResultFolder must be set for file result writer.");
+
+ if (ResultBucketCount <= 0)
+ throw new Exception("ResultBucketCount must be positive: " + ResultBucketCount);
+
+ if (ResultBucketInterval <= 0)
+ throw new Exception("ResultBucketInterval must be positive: " + ResultBucketInterval);
+ }
+ }
+
+ /// <summary>
+ /// Get current throughput across all currenlty running threads.
+ /// </summary>
+ /// <returns>Current throughput.</returns>
+ private IDictionary<string, Tuple<long, long>> GetCurrentThroughput()
+ {
+ var total = new Dictionary<string, Tuple<long, long>>(_descs.Count);
+
+ foreach (var desc in _descs)
+ total[desc.Name] = new Tuple<long, long>(0, 0);
+
+ foreach (var task in _tasks)
+ task.CollectThroughput(total);
+
+ return total;
+ }
+
+ /** <inheritDoc /> */
+ public override string ToString()
+ {
+ var sb = new StringBuilder(GetType().Name).Append('[');
+
+ var first = true;
+
+ var props = BenchmarkUtils.GetProperties(this);
+
+ foreach (var prop in props)
+ {
+ if (first)
+ first = false;
+ else
+ sb.Append(", ");
+
+ sb.Append(prop.Name).Append('=').Append(prop.GetValue(this, null));
+ }
+
+ sb.Append(']');
+
+ return sb.ToString();
+ }
+
+ /* COMMON PUBLIC PROPERTIES. */
+
+ /// <summary>
+ /// Amount of worker threads.
+ /// </summary>
+ public int Threads { get; set; }
+
+ /// <summary>
+ /// Warmup duration in secnods.
+ /// </summary>
+ public int Warmup { get; set; }
+
+ /// <summary>
+ /// Duration in seconds.
+ /// </summary>
+ public int Duration { get; set; }
+
+ /// <summary>
+ /// Maximum amount of operations to perform.
+ /// </summary>
+ public int Operations { get; set; }
+
+ /// <summary>
+ /// Single measurement batch size.
+ /// </summary>
+ public int BatchSize { get; set; }
+
+ /// <summary>
+ /// Maximum amount of errors before benchmark exits.
+ /// </summary>
+ public int MaxErrors { get; set; }
+
+ /// <summary>
+ /// Debug flag.
+ /// </summary>
+ public bool Debug { get; set; }
+
+ /// <summary>
+ /// Result writer type.
+ /// </summary>
+ public string ResultWriter { get; set; }
+
+ /// <summary>
+ /// Result output folder.
+ /// </summary>
+ public string ResultFolder { get; set; }
+
+ /// <summary>
+ /// Percentile result buckets count.
+ /// </summary>
+ public int ResultBucketCount { get; set; }
+
+ /// <summary>
+ /// Percnetile result bucket interval in microseconds.
+ /// </summary>
+ public long ResultBucketInterval { get; set; }
+
+ /* INNER CLASSES. */
+
+ /// <summary>
+ /// Benchmark worker task.
+ /// </summary>
+ private class BenchmarkTask
+ {
+ /** Benchmark. */
+ private readonly BenchmarkBase _benchmark;
+
+ /** Descriptors. */
+ private readonly BenchmarkOperationDescriptor[] _descs;
+
+ /** Results. */
+ private readonly IDictionary<string, Result> _results;
+
+ /** Stop watch. */
+ private readonly Stopwatch _watch = new Stopwatch();
+
+ /** Benchmark state. */
+ private readonly BenchmarkState _state;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="benchmark">Benchmark.</param>
+ /// <param name="descList">Descriptor list.</param>
+ public BenchmarkTask(BenchmarkBase benchmark,
+ ICollection<BenchmarkOperationDescriptor> descList)
+ {
+ _benchmark = benchmark;
+
+ _state = new BenchmarkState();
+
+ _results = new Dictionary<string, Result>(descList.Count);
+
+ var totalWeight = 0;
+
+ var ticksPerSlot = benchmark.ResultBucketInterval*Stopwatch.Frequency/1000000;
+
+ if (ticksPerSlot == 0)
+ throw new Exception("Too low bucket interval: " + benchmark.ResultBucketInterval);
+
+ foreach (var desc in descList)
+ {
+ _results[desc.Name] = new Result(benchmark.ResultBucketCount, ticksPerSlot);
+
+ totalWeight += desc.Weight;
+ }
+
+ _descs = new BenchmarkOperationDescriptor[totalWeight];
+
+ var idx = 0;
+
+ foreach (var desc in descList)
+ {
+ for (var i = 0; i < desc.Weight; i++)
+ _descs[idx++] = desc;
+ }
+ }
+
+ /// <summary>
+ /// Task routine.
+ /// </summary>
+ public void Run()
+ {
+ try
+ {
+ _benchmark.OnThreadReady();
+
+ _benchmark.PrintDebug("Worker thread ready.");
+
+ while (!_benchmark._start)
+ Thread.Sleep(10);
+
+ _benchmark.PrintDebug("Worker thread started benchmark execution.");
+
+ var warmupIteration = true;
+
+ long maxDur = 0;
+
+ long maxOps = _benchmark.Operations;
+
+ while (!_benchmark._stop)
+ {
+ if (warmupIteration && !_benchmark._warmup)
+ {
+ warmupIteration = false;
+
+ _benchmark.OnWarmupFinished();
+
+ _state.StopWarmup();
+
+ _benchmark._barrier.SignalAndWait();
+ }
+
+ if (!warmupIteration)
+ {
+ if (maxOps > 0 && Interlocked.Read(ref _benchmark._curOps) > maxOps)
+ break;
+ }
+
+ var desc = _descs.Length == 1
+ ? _descs[0]
+ : _descs[BenchmarkUtils.GetRandomInt(_descs.Length)];
+
+ var res = true;
+
+ _benchmark.OnBatchStarted(_state);
+
+ _watch.Start();
+
+ try
+ {
+ for (var i = 0; i < _benchmark.BatchSize; i++)
+ {
+ desc.Operation(_state);
+
+ _state.IncrementCounter();
+ }
+
+ if (!warmupIteration)
+ Interlocked.Add(ref _benchmark._curOps, _benchmark.BatchSize);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Exception: " + e);
+
+ res = false;
+
+ if (_benchmark.MaxErrors > 0 &&
+ Interlocked.Increment(ref _benchmark._errorCount) > _benchmark.MaxErrors)
+ {
+ lock (_benchmark)
+ {
+ Console.WriteLine("Benchmark is stopped due to too much errors: " +
+ _benchmark.MaxErrors);
+
+ Environment.Exit(-1);
+ }
+ }
+ }
+ finally
+ {
+ _watch.Stop();
+
+ var curDur = _watch.ElapsedTicks;
+
+ if (res)
+ res = _benchmark.OnBatchFinished(_state, curDur);
+
+ _state.Reset();
+
+ if (curDur > maxDur)
+ {
+ maxDur = curDur;
+
+ _benchmark.PrintDebug("The longest execution [warmup=" + warmupIteration +
+ ", dur(nsec)=" + maxDur*1000000000/Stopwatch.Frequency + ']');
+ }
+
+ _watch.Reset();
+
+ if (!warmupIteration && res)
+ _results[desc.Name].Add(curDur);
+ }
+ }
+ }
+ finally
+ {
+ _benchmark.PrintDebug("Worker thread stopped.");
+
+ _benchmark.OnThreadFinished();
+ }
+ }
+
+ /// <summary>
+ /// Collect throughput for the current task.
+ /// </summary>
+ /// <param name="total">Total result.</param>
+ public void CollectThroughput(IDictionary<string, Tuple<long, long>> total)
+ {
+ foreach (var result in _results)
+ {
+ var old = total[result.Key];
+
+ total[result.Key] = new Tuple<long, long>(old.Item1 + result.Value.Duration,
+ old.Item2 + result.Value.OpCount);
+ }
+ }
+
+ /// <summary>
+ /// Collect percnetiles for the current task.
+ /// </summary>
+ /// <param name="total"></param>
+ public void CollectPercentiles(IDictionary<string, long[]> total)
+ {
+ foreach (var result in _results)
+ {
+ var arr = total[result.Key];
+
+ for (var i = 0; i < arr.Length; i++)
+ arr[i] += result.Value.Slots[i];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Timeout task to stop execution.
+ /// </summary>
+ private class TimeoutTask
+ {
+ /** Benchmark. */
+ private readonly BenchmarkBase _benchmark;
+
+ /** Duration. */
+ private readonly long _dur;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="benchmark">Benchmark.</param>
+ /// <param name="dur">Duration.</param>
+ public TimeoutTask(BenchmarkBase benchmark, long dur)
+ {
+ _benchmark = benchmark;
+ _dur = dur;
+ }
+
+ /// <summary>
+ /// Task routine.
+ /// </summary>
+ public void Run()
+ {
+ try
+ {
+ Thread.Sleep(TimeSpan.FromSeconds(_dur));
+ }
+ finally
+ {
+ _benchmark._stop = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Warmup task to clear warmup flag.
+ /// </summary>
+ private class WarmupTask
+ {
+ /** Benchmark. */
+ private readonly BenchmarkBase _benchmark;
+
+ /** Duration. */
+ private readonly long _dur;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="benchmark">Benchmark.</param>
+ /// <param name="dur">Duration.</param>
+ public WarmupTask(BenchmarkBase benchmark, long dur)
+ {
+ _benchmark = benchmark;
+ _dur = dur;
+ }
+
+ /// <summary>
+ /// Task routine.
+ /// </summary>
+ public void Run()
+ {
+ try
+ {
+ Thread.Sleep(TimeSpan.FromSeconds(_dur));
+ }
+ finally
+ {
+ _benchmark._warmup = false;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Throughput write task.
+ /// </summary>
+ private class ThroughputTask
+ {
+ /** Benchmark. */
+ private readonly BenchmarkBase _benchmark;
+
+ /** Last recorded result. */
+ private IDictionary<string, Tuple<long, long>> _lastResults;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="benchmark">Benchmark.</param>
+ public ThroughputTask(BenchmarkBase benchmark)
+ {
+ _benchmark = benchmark;
+ }
+
+ public void Run()
+ {
+ while (!_benchmark._stop)
+ {
+ Thread.Sleep(1000);
+
+ if (_benchmark._start && !_benchmark._warmup)
+ {
+ var results = _benchmark.GetCurrentThroughput();
+
+ if (_benchmark._finishedThreads > 0)
+ return; // Threads are stopping, do not collect any more.
+
+ foreach (var pair in results)
+ {
+ Tuple<long, long> old;
+
+ if (_lastResults != null && _lastResults.TryGetValue(pair.Key, out old))
+ _benchmark._writer.WriteThroughput(pair.Key, pair.Value.Item1 - old.Item1,
+ pair.Value.Item2 - old.Item2);
+ else
+ _benchmark._writer.WriteThroughput(pair.Key, pair.Value.Item1,
+ pair.Value.Item2);
+ }
+
+ _lastResults = results;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Benchmark result. Specific for each operation.
+ /// </summary>
+ private class Result
+ {
+ /** Slots. */
+ public readonly long[] Slots;
+
+ /** Slot duration in ticks. */
+ private readonly long _slotDuration;
+
+ /** Total operations count. */
+ public long OpCount;
+
+ /** Total duration. */
+ public long Duration;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="slotCnt">Slot count.</param>
+ /// <param name="slotDuration">Slot duration in ticks.</param>
+ public Result(long slotCnt, long slotDuration)
+ {
+ Slots = new long[slotCnt];
+
+ _slotDuration = slotDuration;
+ }
+
+ /// <summary>
+ /// Add result.
+ /// </summary>
+ /// <param name="curDur">Current duration in ticks.</param>
+ public void Add(long curDur)
+ {
+ var idx = (int) (curDur/_slotDuration);
+
+ if (idx >= Slots.Length)
+ idx = Slots.Length - 1;
+
+ Slots[idx] += 1;
+
+ OpCount++;
+ Duration += curDur;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkOperationDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkOperationDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkOperationDescriptor.cs
new file mode 100644
index 0000000..1233b4c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkOperationDescriptor.cs
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks
+{
+ using System;
+
+ /// <summary>
+ /// Benchmark operation descriptor.
+ /// </summary>
+ internal class BenchmarkOperationDescriptor
+ {
+ /// <summary>
+ /// Create new operation descriptor.
+ /// </summary>
+ /// <param name="name">Name.</param>
+ /// <param name="operation">Operation.</param>
+ /// <param name="weight">Weight.</param>
+ /// <returns>Operation descriptor.</returns>
+ public static BenchmarkOperationDescriptor Create(string name, Action<BenchmarkState> operation, int weight)
+ {
+ if (string.IsNullOrEmpty(name))
+ throw new Exception("Operation name cannot be null or empty.");
+
+ if (operation == null)
+ throw new Exception("Operation cannot be null: " + name);
+
+ if (weight <= 0)
+ throw new Exception("Operation weight cannot be negative [name=" + name + ", weight=" + weight + ']');
+
+ return new BenchmarkOperationDescriptor
+ {
+ Name = name,
+ Operation = operation,
+ Weight = weight
+ };
+ }
+
+ /// <summary>
+ /// Unique operation name.
+ /// </summary>
+ public string Name { get; private set; }
+
+ /// <summary>
+ /// Operation delegate.
+ /// </summary>
+ public Action<BenchmarkState> Operation { get; private set; }
+
+ /// <summary>
+ /// Weight.
+ /// </summary>
+ public int Weight { get; private set; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs
new file mode 100644
index 0000000..506106e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks
+{
+ using System;
+ using System.Diagnostics;
+ using System.Text;
+ using Apache.Ignite.Benchmarks.Portable;
+
+ /// <summary>
+ /// Benchmark runner.
+ /// </summary>
+ internal class BenchmarkRunner
+ {
+ /// <summary>
+ /// Entry point.
+ /// </summary>
+ /// <param name="args">Arguments.</param>
+ // ReSharper disable once RedundantAssignment
+ public static void Main(string[] args)
+ {
+ args = new[] {
+ typeof(PortableWriteBenchmark).FullName,
+ "-ConfigPath", @"modules\platforms\dotnet\Apache.Ignite.Benchmarks\Config\benchmark.xml",
+ "-Threads", "1",
+ "-Warmup", "0",
+ "-Duration", "60",
+ "-BatchSize", "1000"
+ };
+
+ var gcSrv = System.Runtime.GCSettings.IsServerGC;
+
+ Console.WriteLine("GC Server: " + gcSrv);
+
+ if (!gcSrv)
+ Console.WriteLine("WARNING! GC server mode is disabled. This could yield in bad preformance.");
+
+ Console.WriteLine("DotNet benchmark process started: " + Process.GetCurrentProcess().Id);
+
+ var argsStr = new StringBuilder();
+
+ foreach (var arg in args)
+ argsStr.Append(arg + " ");
+
+ if (args.Length < 1)
+ throw new Exception("Not enough arguments: " + argsStr);
+
+ Console.WriteLine("Arguments: " + argsStr);
+
+ var benchmarkType = Type.GetType(args[0]);
+
+ if (benchmarkType == null)
+ throw new InvalidOperationException("Could not find benchmark type: " + args[0]);
+
+ var benchmark = (BenchmarkBase)Activator.CreateInstance(benchmarkType);
+
+ for (var i = 1; i < args.Length; i++)
+ {
+ var arg = args[i];
+
+ if (arg.StartsWith("-"))
+ arg = arg.Substring(1);
+ else
+ continue;
+
+ var prop = BenchmarkUtils.GetProperty(benchmark, arg);
+
+ if (prop != null)
+ benchmark.Configure(prop.Name, prop.PropertyType == typeof(bool) ? bool.TrueString : args[++i]);
+ }
+
+ benchmark.Run();
+
+#if (DEBUG)
+ Console.ReadLine();
+#endif
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkState.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkState.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkState.cs
new file mode 100644
index 0000000..cc05c15
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkState.cs
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks
+{
+ using System;
+
+ /// <summary>
+ /// Benchmark state.
+ /// </summary>
+ internal class BenchmarkState
+ {
+ /** Warmup flag. */
+ private bool _warmup = true;
+
+ /** Counter within the batch. */
+ private int _counter;
+
+ /** Array of attached objects. */
+ private object[] _attachedObjects;
+
+ /// <summary>
+ /// Reset state.
+ /// </summary>
+ public void Reset()
+ {
+ _counter = 0;
+ _attachedObjects = null;
+ }
+
+ /// <summary>
+ /// Clear warmup flag.
+ /// </summary>
+ public void StopWarmup()
+ {
+ _warmup = false;
+ }
+
+ /// <summary>
+ /// Increment counter.
+ /// </summary>
+ public void IncrementCounter()
+ {
+ _counter++;
+ }
+
+ /// <summary>
+ /// Warmup flag.
+ /// </summary>
+ public bool Warmup
+ {
+ get { return _warmup; }
+ }
+
+ /// <summary>
+ /// Counter within the batch.
+ /// </summary>
+ public int Counter
+ {
+ get { return _counter; }
+ }
+
+ /// <summary>
+ /// Get/set attached object.
+ /// </summary>
+ /// <param name="idx">Index.</param>
+ /// <returns>Attahced object.</returns>
+ public object this[int idx]
+ {
+ get
+ {
+ return (_attachedObjects == null || idx >= _attachedObjects.Length) ? null : _attachedObjects[idx];
+ }
+
+ set
+ {
+ if (_attachedObjects == null)
+ _attachedObjects = new object[idx + 1];
+ else if (idx >= _attachedObjects.Length)
+ {
+ var arr0 = new object[idx + 1];
+
+ Array.Copy(_attachedObjects, 0, arr0, 0, arr0.Length);
+
+ _attachedObjects = arr0;
+ }
+
+ _attachedObjects[idx] = value;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkUtils.cs
new file mode 100644
index 0000000..e2543af
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkUtils.cs
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks
+{
+ using System;
+ using System.Linq;
+ using System.Reflection;
+ using System.Text;
+ using System.Threading;
+ using Apache.Ignite.Benchmarks.Model;
+
+ /// <summary>
+ /// Utility methods for benchmarks.
+ /// </summary>
+ internal static class BenchmarkUtils
+ {
+ /** Property binding flags. */
+ private static readonly BindingFlags PropFlags = BindingFlags.Instance | BindingFlags.Public;
+
+ /** Thread-local random. */
+ private static readonly ThreadLocal<Random> Rand;
+
+ /** Cached ANSI chcracters. */
+ private static readonly char[] Chars;
+
+ /** Seed to randoms. */
+ private static int _seedCtr;
+
+ /// <summary>
+ /// Static initializer.
+ /// </summary>
+ static BenchmarkUtils()
+ {
+ Rand = new ThreadLocal<Random>(() =>
+ {
+ var seed = Interlocked.Add(ref _seedCtr, 100);
+
+ return new Random(seed);
+ });
+
+ Chars = new char[10 + 26 + 26];
+
+ var pos = 0;
+
+ for (var i = '0'; i < '0' + 10; i++)
+ Chars[pos++] = i;
+
+ for (var i = 'A'; i < 'A' + 26; i++)
+ Chars[pos++] = i;
+
+ for (var i = 'a'; i < 'a' + 26; i++)
+ Chars[pos++] = i;
+ }
+
+ /// <summary>
+ /// Generate random integer.
+ /// </summary>
+ /// <param name="max">Maximum value (exclusive).</param>
+ /// <returns></returns>
+ public static int GetRandomInt(int max)
+ {
+ return GetRandomInt(0, max);
+ }
+
+ /// <summary>
+ /// Generate random integer.
+ /// </summary>
+ /// <param name="min">Minimum value (inclusive).</param>
+ /// <param name="max">Maximum value (exclusive).</param>
+ /// <returns></returns>
+ public static int GetRandomInt(int min, int max)
+ {
+ return Rand.Value.Next(min, max);
+ }
+
+ /// <summary>
+ /// Generate random string.
+ /// </summary>
+ /// <param name="len">Length.</param>
+ /// <returns>String.</returns>
+ public static string GetRandomString(int len)
+ {
+ var rand = Rand.Value;
+
+ var sb = new StringBuilder();
+
+ for (var i = 0; i < len; i++)
+ sb.Append(Chars[rand.Next(Chars.Length)]);
+
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Generate random address.
+ /// </summary>
+ /// <returns>Address.</returns>
+ public static Address GetRandomAddress()
+ {
+ return new Address(
+ GetRandomString(15),
+ GetRandomString(20),
+ GetRandomInt(1, 500),
+ GetRandomInt(1, 35)
+ );
+ }
+
+ /// <summary>
+ /// Generate random company.
+ /// </summary>
+ /// <returns>Company.</returns>
+ public static Company GetRandomCompany()
+ {
+ return new Company(
+ GetRandomInt(0, 100),
+ GetRandomString(20),
+ GetRandomInt(100, 3000),
+ GetRandomAddress(),
+ GetRandomString(20)
+ );
+ }
+
+ /// <summary>
+ /// Generate random employee.
+ /// </summary>
+ /// <param name="payload">Payload size.</param>
+ /// <returns>Employee.</returns>
+ public static Employee GetRandomEmployee(int payload)
+ {
+ return new Employee(
+ GetRandomInt(0, 1000),
+ GetRandomString(15),
+ GetRandomInt(0, 1000),
+ GetRandomInt(18, 60),
+ (Sex)GetRandomInt(0, 1),
+ GetRandomInt(10000, 30000),
+ GetRandomAddress(),
+ (Department)GetRandomInt(0, 5),
+ payload
+ );
+ }
+
+ /// <summary>
+ /// List all properties present in the given object.
+ /// </summary>
+ /// <param name="obj">Object.</param>
+ /// <returns>Properties.</returns>
+ public static PropertyInfo[] GetProperties(object obj)
+ {
+ return obj.GetType().GetProperties(PropFlags);
+ }
+
+ /// <summary>
+ /// Find property with the given name in the object.
+ /// </summary>
+ /// <param name="obj">Object.</param>
+ /// <param name="name">Name.</param>
+ /// <returns>Property.</returns>
+ public static PropertyInfo GetProperty(object obj, string name)
+ {
+ return GetProperties(obj)
+ .FirstOrDefault(prop => prop.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
+ }
+
+ /// <summary>
+ /// Set property on the given object.
+ /// </summary>
+ /// <param name="obj">Object.</param>
+ /// <param name="prop">Property.</param>
+ /// <param name="val">Value.</param>
+ public static void SetProperty(object obj, PropertyInfo prop, string val)
+ {
+ object val0;
+
+ var propType = prop.PropertyType;
+
+ if (propType == typeof(int))
+ {
+ try
+ {
+ val0 = int.Parse(val);
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Failed to parse property value [property=" + prop.Name +
+ ", value=" + val + ']', e);
+ }
+ }
+ else if (propType == typeof(long))
+ {
+ try
+ {
+ val0 = long.Parse(val);
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Failed to parse property value [property=" + prop.Name +
+ ", value=" + val + ']', e);
+ }
+ }
+ else if (propType == typeof(bool))
+ {
+ try
+ {
+ val0 = bool.Parse(val);
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Failed to parse property value [property=" + prop.Name +
+ ", value=" + val + ']', e);
+ }
+ }
+ else if (propType == typeof(string))
+ val0 = val;
+ else
+ throw new Exception("Unsupported property type [property=" + prop.Name +
+ ", type=" + propType.Name + ']');
+
+ prop.SetValue(obj, val0, null);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Config/benchmark.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Config/benchmark.xml b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Config/benchmark.xml
new file mode 100644
index 0000000..8bda9e8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Config/benchmark.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean class="org.apache.ignite.configuration.IgniteConfiguration">
+ <property name="localHost" value="127.0.0.1"/>
+
+ <property name="metricsLogFrequency" value="0"/>
+
+ <property name="cacheConfiguration">
+ <list>
+ <bean id="cache" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache"/>
+ <property name="cacheMode" value="PARTITIONED"/>
+ <property name="writeSynchronizationMode" value="FULL_SYNC"/>
+ <property name="rebalanceMode" value="SYNC"/>
+ <property name="backups" value="0"/>
+ <property name="atomicityMode" value="ATOMIC"/>
+ </bean>
+ </list>
+ </property>
+
+ <property name="discoverySpi">
+ <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+ <property name="ipFinder">
+ <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+ <property name="addresses">
+ <list>
+ <value>127.0.0.1:47500</value>
+ </list>
+ </property>
+ </bean>
+ </property>
+ </bean>
+ </property>
+ </bean>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/ClosureBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/ClosureBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/ClosureBenchmark.cs
new file mode 100644
index 0000000..a6eb244
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/ClosureBenchmark.cs
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Compute;
+
+ /// <summary>
+ /// Compute func benchmark.
+ /// </summary>
+ internal class ClosureBenchmark : PlatformBenchmarkBase
+ {
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("ExecuteClosureTask", ExecuteClosureTask, 1));
+ }
+
+ /// <summary>
+ /// Executes closure.
+ /// </summary>
+ private void ExecuteClosureTask(BenchmarkState state)
+ {
+ Node.GetCompute().Call(new MyClosure("zzzz"));
+ }
+ }
+
+ /// <summary>
+ /// Compute func.
+ /// </summary>
+ internal class MyClosure : IComputeFunc<int>
+ {
+ /** */
+ private readonly string _s;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MyClosure"/> class.
+ /// </summary>
+ /// <param name="s">The s.</param>
+ public MyClosure(string s)
+ {
+ _s = s;
+ }
+
+ /** <inheritdoc /> */
+ public int Invoke()
+ {
+ return _s.Length;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAsyncBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAsyncBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAsyncBenchmark.cs
new file mode 100644
index 0000000..d7e0c41
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetAsyncBenchmark.cs
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Benchmarks.Model;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Async Get benchmark.
+ /// </summary>
+ internal class GetAsyncBenchmark : PlatformBenchmarkBase
+ {
+ /** Cache name. */
+ private const string CacheName = "cache";
+
+ /** Native cache wrapper. */
+ private ICache<int, Employee> _cache;
+
+ /** <inheritDoc /> */
+ protected override void OnStarted()
+ {
+ base.OnStarted();
+
+ _cache = Node.GetCache<int, Employee>(CacheName);
+
+ for (int i = 0; i < Emps.Length; i++)
+ _cache.Put(i, Emps[i]);
+
+ _cache = _cache.WithAsync();
+ }
+
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("GetAsync", GetAsync, 1));
+ }
+
+ /// <summary>
+ /// Cache getAsync.
+ /// </summary>
+ private void GetAsync(BenchmarkState state)
+ {
+ int idx = BenchmarkUtils.GetRandomInt(Dataset);
+
+ _cache.Get(idx);
+
+ _cache.GetFuture<Employee>().ToTask().Wait();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
new file mode 100644
index 0000000..5d69669
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/GetBenchmark.cs
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Benchmarks.Model;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Cache Get benchmark.
+ /// </summary>
+ internal class GetBenchmark : PlatformBenchmarkBase
+ {
+ /** Cache name. */
+ private const string CacheName = "cache";
+
+ /** Native cache wrapper. */
+ private ICache<int, Employee> _cache;
+
+ /** <inheritDoc /> */
+ protected override void OnStarted()
+ {
+ base.OnStarted();
+
+ _cache = Node.GetCache<int, Employee>(CacheName);
+
+ for (int i = 0; i < Emps.Length; i++)
+ _cache.Put(i, Emps[i]);
+ }
+
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("Get", Get, 1));
+ }
+
+ /// <summary>
+ /// Cache get.
+ /// </summary>
+ private void Get(BenchmarkState state)
+ {
+ var idx = BenchmarkUtils.GetRandomInt(Dataset);
+
+ _cache.Get(idx);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PlatformBenchmarkBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PlatformBenchmarkBase.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PlatformBenchmarkBase.cs
new file mode 100644
index 0000000..87fb2e9
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PlatformBenchmarkBase.cs
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Benchmarks.Model;
+ using Apache.Ignite.Core;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Base class for all platform benchmarks.
+ /// </summary>
+ internal abstract class PlatformBenchmarkBase : BenchmarkBase
+ {
+ /** Default dataset. */
+ private const int DfltDataset = 100000;
+
+ /** Default payload. */
+ private const int DfltPayload = 128;
+
+ /** Native node. */
+ protected IIgnite Node;
+
+ /** Employees. */
+ protected Employee[] Emps;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ protected PlatformBenchmarkBase()
+ {
+ Dataset = DfltDataset;
+ Payload = DfltPayload;
+ }
+
+ /** <inheritDoc /> */
+ protected override void OnStarted()
+ {
+ Emps = new Employee[Dataset];
+
+ for (var i = 0; i < Emps.Length; i++)
+ Emps[i] = BenchmarkUtils.GetRandomEmployee(Payload);
+
+ var cfg = new IgniteConfiguration
+ {
+ PortableConfiguration = GetPortableConfiguration(),
+ JvmOptions = new List<string>
+ {
+ "-Xms2g",
+ "-Xmx2g",
+ "-DIGNITE_QUIET=false",
+ "-DIGNITE_NO_SHUTDOWN_HOOK=true"
+ },
+ JvmClasspath = Classpath ?? Core.Impl.Common.Classpath.CreateClasspath(),
+ JvmDllPath = DllPath,
+ SpringConfigUrl = ConfigPath
+ };
+
+ Node = Ignition.Start(cfg);
+ }
+
+ /// <summary>
+ /// Get portable configuration.
+ /// </summary>
+ /// <returns>Portable configuration.</returns>
+ private static PortableConfiguration GetPortableConfiguration()
+ {
+ return new PortableConfiguration
+ {
+ TypeConfigurations = new List<PortableTypeConfiguration>
+ {
+ new PortableTypeConfiguration(typeof (Address)),
+ new PortableTypeConfiguration(typeof (Company)),
+ new PortableTypeConfiguration(typeof (Employee)),
+ new PortableTypeConfiguration(typeof (MyClosure)),
+ new PortableTypeConfiguration(typeof (MyJob))
+ },
+ DefaultMetadataEnabled = false
+ };
+ }
+
+ /// <summary>
+ /// Classpath.
+ /// </summary>
+ public string Classpath { get; set; }
+
+ /// <summary>
+ /// Path to JVM.DLL.
+ /// </summary>
+ public string DllPath { get; set; }
+
+ /// <summary>
+ /// Path to XML configuration.
+ /// </summary>
+ public string ConfigPath { get; set; }
+
+ /// <summary>
+ /// Data set size.
+ /// </summary>
+ public int Dataset { get; set; }
+
+ /// <summary>
+ /// Payload.
+ /// </summary>
+ public int Payload { get; set; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutAsyncBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutAsyncBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutAsyncBenchmark.cs
new file mode 100644
index 0000000..475a0c6
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutAsyncBenchmark.cs
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Async Put benchmark.
+ /// </summary>
+ internal class PutAsyncBenchmark : PlatformBenchmarkBase
+ {
+ /** Cache name. */
+ private const string CacheName = "cache";
+
+ /** Native cache wrapper. */
+ private ICache<object, object> _cache;
+
+ /** <inheritDoc /> */
+ protected override void OnStarted()
+ {
+ base.OnStarted();
+
+ _cache = Node.GetCache<object, object>(CacheName).WithAsync();
+ }
+
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("PutAsync", PutAsync, 1));
+ }
+
+ /// <summary>
+ /// Cache putAsync.
+ /// </summary>
+ private void PutAsync(BenchmarkState state)
+ {
+ int idx = BenchmarkUtils.GetRandomInt(Dataset);
+
+ _cache.Put(idx, Emps[idx]);
+
+ _cache.GetFuture<object>().Get();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutBenchmark.cs
new file mode 100644
index 0000000..d0c6f4b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/PutBenchmark.cs
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Cache;
+
+ /// <summary>
+ /// Cache put benchmark.
+ /// </summary>
+ internal class PutBenchmark : PlatformBenchmarkBase
+ {
+ /** Cache name. */
+ private const string CacheName = "cache";
+
+ /** Native cache wrapper. */
+ private ICache<object, object> _cache;
+
+ /** <inheritDoc /> */
+ protected override void OnStarted()
+ {
+ base.OnStarted();
+
+ _cache = Node.GetCache<object, object>(CacheName);
+ }
+
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("Put", Put, 1));
+ }
+
+ /// <summary>
+ /// Cache put.
+ /// </summary>
+ private void Put(BenchmarkState state)
+ {
+ int idx = BenchmarkUtils.GetRandomInt(Dataset);
+
+ _cache.Put(idx, Emps[idx]);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TaskBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TaskBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TaskBenchmark.cs
new file mode 100644
index 0000000..6a2585c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TaskBenchmark.cs
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Compute;
+
+ /// <summary>
+ /// Compute task benchmark.
+ /// </summary>
+ internal class TaskBenchmark : PlatformBenchmarkBase
+ {
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("ExecuteEmptyTask", ExecuteEmptyTask, 1));
+ }
+
+ /// <summary>
+ /// Executes task.
+ /// </summary>
+ private void ExecuteEmptyTask(BenchmarkState state)
+ {
+ Node.GetCompute().Execute(new MyEmptyTask(), "zzzz");
+ }
+ }
+
+ /// <summary>
+ /// Compute task.
+ /// </summary>
+ internal class MyEmptyTask : IComputeTask<object, object, object>
+ {
+ /** <inheritDoc /> */
+ public IDictionary<IComputeJob<object>, IClusterNode> Map(IList<IClusterNode> subgrid, object arg)
+ {
+ return new Dictionary<IComputeJob<object>, IClusterNode>
+ {
+ {new MyJob((string) arg), subgrid[0]}
+ };
+ }
+
+ /** <inheritDoc /> */
+ public ComputeJobResultPolicy Result(IComputeJobResult<object> res, IList<IComputeJobResult<object>> rcvd)
+ {
+ return ComputeJobResultPolicy.Wait;
+ }
+
+ /** <inheritDoc /> */
+ public object Reduce(IList<IComputeJobResult<object>> results)
+ {
+ return results.Count == 0 ? null : results[0];
+ }
+ }
+
+ /// <summary>
+ /// Compute job.
+ /// </summary>
+ internal class MyJob : IComputeJob<object>
+ {
+ /** */
+ private readonly string _s;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MyJob"/> class.
+ /// </summary>
+ /// <param name="s">The s.</param>
+ public MyJob(string s)
+ {
+ _s = s;
+ }
+
+ /** <inheritDoc /> */
+ public object Execute()
+ {
+ return _s.Length;
+ }
+
+ /** <inheritDoc /> */
+ public void Cancel()
+ {
+ // No-op.
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TxBenchmark.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TxBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TxBenchmark.cs
new file mode 100644
index 0000000..3666d45
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Interop/TxBenchmark.cs
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Interop
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Transactions;
+
+ /// <summary>
+ /// Transactions benchmark.
+ /// </summary>
+ internal class TxBenchmark : PlatformBenchmarkBase
+ {
+ /** Cache name. */
+ private const string CacheName = "cache_tx";
+
+ /** Native cache wrapper. */
+ private ICache<object, object> _cache;
+
+ /** <inheritDoc /> */
+ protected override void OnStarted()
+ {
+ base.OnStarted();
+
+ _cache = Node.GetCache<object, object>(CacheName);
+ }
+
+ /** <inheritDoc /> */
+ protected override void GetDescriptors(ICollection<BenchmarkOperationDescriptor> descs)
+ {
+ descs.Add(BenchmarkOperationDescriptor.Create("PutTx", PutTx, 1));
+ }
+
+ /// <summary>
+ /// Cache put.
+ /// </summary>
+ private void PutTx(BenchmarkState state)
+ {
+ int idx = BenchmarkUtils.GetRandomInt(Dataset);
+
+ using (var tx = Node.GetTransactions().TxStart(TransactionConcurrency.Pessimistic,
+ TransactionIsolation.RepeatableRead))
+ {
+ _cache.Put(idx, Emps[idx]);
+
+ tx.Commit();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3852b0b6/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Address.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Address.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Address.cs
new file mode 100644
index 0000000..871814c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/Model/Address.cs
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Benchmarks.Model
+{
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Address.
+ /// </summary>
+ internal class Address : IPortableMarshalAware
+ {
+ /// <summary>
+ /// City.
+ /// </summary>
+ public string City { get; set; }
+
+ /// <summary>
+ /// Street.
+ /// </summary>
+ public string Street { get; set; }
+
+ /// <summary>
+ /// Street number.
+ /// </summary>
+ public int StreetNumber { get; set; }
+
+ /// <summary>
+ /// Flat number.
+ /// </summary>
+ public int FlatNumber { get; set; }
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="city">City.</param>
+ /// <param name="street">Street.</param>
+ /// <param name="streetNum">Street number.</param>
+ /// <param name="flatNum">Flat number.</param>
+ public Address(string city, string street, int streetNum, int flatNum)
+ {
+ City = city;
+ Street = street;
+ StreetNumber = streetNum;
+ FlatNumber = flatNum;
+ }
+
+ /** <inheritDoc /> */
+ public void WritePortable(IPortableWriter writer)
+ {
+ writer.WriteInt("streetNum", StreetNumber);
+ writer.WriteInt("flatNum", FlatNumber);
+ writer.WriteString("city", City);
+ writer.WriteString("street", Street);
+ }
+
+ /** <inheritDoc /> */
+ public void ReadPortable(IPortableReader reader)
+ {
+ StreetNumber = reader.ReadInt("streetNum");
+ FlatNumber = reader.ReadInt("flatNum");
+ City = reader.ReadString("city");
+ Street = reader.ReadString("street");
+ }
+ }
+}