Create nanoFramework.Benchmark with sample.
This commit is contained in:
Родитель
266203fa6c
Коммит
0f48e0aa23
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using nanoFramework.Benchmark.Attributes;
|
||||
using nanoFramework.Logging.Debug;
|
||||
|
||||
namespace nanoFramework.Benchmark.Sample
|
||||
{
|
||||
[ItterationCount(11)]
|
||||
[DebugLogger]
|
||||
[CsvParser]
|
||||
[ConsoleParser]
|
||||
public class CreateRadomCollectionBenchmark
|
||||
{
|
||||
public int NumbersToCreateCount { get; set; } = 1000;
|
||||
|
||||
private Random random;
|
||||
|
||||
[Setup]
|
||||
public void Setup()
|
||||
{
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CreateRandomArray()
|
||||
{
|
||||
var arrayOfInts = new int[NumbersToCreateCount];
|
||||
for (int i = 0; i < NumbersToCreateCount; i++)
|
||||
{
|
||||
var value = random.Next();
|
||||
arrayOfInts[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void CreateRandomList()
|
||||
{
|
||||
var listOfInts = new ArrayList();
|
||||
for (int i = 0; i < NumbersToCreateCount; i++)
|
||||
{
|
||||
var value = random.Next();
|
||||
listOfInts.Add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Sample
|
||||
{
|
||||
internal interface IAssemblyHandler
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace nanoFramework.Benchmark.Sample
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
Debug.WriteLine("Hello from nanoFramework.Benchmark!");
|
||||
|
||||
BenchmarkRunner.Run(typeof(IAssemblyHandler).Assembly);
|
||||
|
||||
Thread.Sleep(Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CSharp.BlankApplication")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CSharp.BlankApplication")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectGuid>2f7d544d-0538-427d-a2d0-54b77c3f5f0a</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<RootNamespace>nanoFramework.Benchmark.Sample</RootNamespace>
|
||||
<AssemblyName>nanoFramework.Benchmark.Sample</AssemblyName>
|
||||
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="CreateRadomCollectionBenchmark.cs" />
|
||||
<Compile Include="IAssemblyHandler.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib">
|
||||
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Logging">
|
||||
<HintPath>..\packages\nanoFramework.Logging.1.1.2\lib\nanoFramework.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Logging.Serial">
|
||||
<HintPath>..\packages\nanoFramework.Logging.Serial.1.1.2\lib\nanoFramework.Logging.Serial.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Runtime.Events">
|
||||
<HintPath>..\packages\nanoFramework.Runtime.Events.1.10.0\lib\nanoFramework.Runtime.Events.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Collections">
|
||||
<HintPath>..\packages\nanoFramework.System.Collections.1.4.0\lib\nanoFramework.System.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Text">
|
||||
<HintPath>..\packages\nanoFramework.System.Text.1.2.3\lib\nanoFramework.System.Text.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Ports">
|
||||
<HintPath>..\packages\nanoFramework.System.IO.Ports.1.1.6\lib\System.IO.Ports.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Streams">
|
||||
<HintPath>..\packages\nanoFramework.System.IO.Streams.1.1.9\lib\System.IO.Streams.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\nanoFramework.Benchmark\nanoFramework.Benchmark.nfproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
|
||||
<ProjectExtensions>
|
||||
<ProjectCapabilities>
|
||||
<ProjectConfigurationsDeclaredAsItems />
|
||||
</ProjectCapabilities>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Logging" version="1.1.2" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Logging.Serial" version="1.1.2" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Runtime.Events" version="1.10.0" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Collections" version="1.4.0" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.IO.Ports" version="1.1.6" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.IO.Streams" version="1.1.9" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Text" version="1.2.3" targetFramework="netnano1.0" />
|
||||
</packages>
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32630.192
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Benchmark", "nanoFramework.Benchmark\nanoFramework.Benchmark.nfproj", "{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}"
|
||||
EndProject
|
||||
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Benchmark.Sample", "nanoFramework.Benchmark.Sample\nanoFramework.Benchmark.Sample.nfproj", "{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B2827CB3-4BCD-40C0-A82D-5AB476E84CE4}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F7D544D-0538-427D-A2D0-54B77C3F5F0A}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {84ADC838-8FF6-4A3F-A697-E9A5A5C63DC7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,11 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Attributes.Abstract
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public abstract class LoggerAttribute : Attribute
|
||||
{
|
||||
public abstract ILogger Logger { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using nanoFramework.Benchmark.Parser;
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Attributes.Abstract
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public abstract class ParserAttribute : Attribute
|
||||
{
|
||||
private static IResultParser parser;
|
||||
public IResultParser ResultParser
|
||||
{
|
||||
get
|
||||
{
|
||||
if (parser == null)
|
||||
{
|
||||
parser = CreateNewResultParser;
|
||||
}
|
||||
|
||||
return parser;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract IResultParser CreateNewResultParser { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using nanoFramework.Benchmark.Attributes.Abstract;
|
||||
using nanoFramework.Benchmark.Parser;
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public sealed class ConsoleParserAttribute : ParserAttribute
|
||||
{
|
||||
public override IResultParser CreateNewResultParser => new ConsoleParser();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using nanoFramework.Benchmark.Attributes.Abstract;
|
||||
using nanoFramework.Benchmark.Parser;
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public sealed class CsvParserAttribute : ParserAttribute
|
||||
{
|
||||
public override IResultParser CreateNewResultParser => new CsvParser();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using nanoFramework.Benchmark.Attributes.Abstract;
|
||||
using nanoFramework.Logging.Debug;
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public sealed class DebugLoggerAttribute : LoggerAttribute
|
||||
{
|
||||
const string DebugLoggerCategory = "DebugLogger";
|
||||
|
||||
private static ILogger logger;
|
||||
public override ILogger Logger
|
||||
{
|
||||
get
|
||||
{
|
||||
if (logger == null)
|
||||
{
|
||||
logger = new DebugLoggerFactory().CreateLogger(DebugLoggerCategory);
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class ItterationCountAttribute : Attribute
|
||||
{
|
||||
public const ushort DefaultItterationCount = 10;
|
||||
|
||||
public int Count { get; }
|
||||
|
||||
public ItterationCountAttribute(int count)
|
||||
{
|
||||
Count = count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public sealed class BenchmarkAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using nanoFramework.Benchmark.Helpers;
|
||||
using nanoFramework.Benchmark.Parser;
|
||||
using nanoFramework.Benchmark.Result;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace nanoFramework.Benchmark
|
||||
{
|
||||
public static class BenchmarkRunner
|
||||
{
|
||||
private static string[] ExcludedClassNamesFromBenchmarks =
|
||||
{
|
||||
"Program"
|
||||
};
|
||||
|
||||
public static void Run(Assembly assembly)
|
||||
{
|
||||
var classes = assembly.GetTypes();
|
||||
foreach (var type in classes)
|
||||
{
|
||||
if (!type.IsClass)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.IsInterface)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ExcludedClassNamesFromBenchmarks.Contains(type.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RunClass(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunClass(Type classType)
|
||||
{
|
||||
if (!classType.IsClass)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
if (classType.IsAbstract)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
#region SetupRunner
|
||||
var itterationCount = SettingsHelper.GetItterationCount(classType);
|
||||
var logger = SettingsHelper.GetLoggerIfExists(classType);
|
||||
var parsers = SettingsHelper.GetResultParser(classType);
|
||||
#endregion
|
||||
|
||||
var classToInvokeMethodOn = ReflectionHelpers.CreateObjectViaReflection(classType);
|
||||
if (classToInvokeMethodOn == null)
|
||||
{
|
||||
logger?.LogError($"Unable to create instance of {classType.FullName} class. Make sure that class contains parameterless constructor.");
|
||||
return;
|
||||
}
|
||||
|
||||
var allMethods = classType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
||||
var setupMethod = (MethodInfo)ReflectionHelpers.GetSetupMethodIfExists(allMethods);
|
||||
setupMethod?.Invoke(classToInvokeMethodOn, null);
|
||||
|
||||
var methodResults = new ArrayList();
|
||||
foreach (MethodInfo method in ReflectionHelpers.GetBenchmarkMethods(allMethods, logger))
|
||||
{
|
||||
var result = Run(classToInvokeMethodOn, method, itterationCount);
|
||||
methodResults.Add(new MethodResult(method.Name, result));
|
||||
}
|
||||
|
||||
var benchmarkResult = new SingleBenchmarkResult(
|
||||
ArrayListHelper.ConvertFromArrayListToMethodResultArray(methodResults),
|
||||
classType.Name,
|
||||
itterationCount);
|
||||
|
||||
InvokeParses(benchmarkResult, parsers, logger);
|
||||
}
|
||||
|
||||
private static SingleTestResult[] Run(object classToInvokeMethodOn, MethodInfo method, int itterationCount)
|
||||
{
|
||||
var resultCollection = new SingleTestResult[itterationCount];
|
||||
|
||||
// There is a check if method has no parameters before
|
||||
var parameters = new object[0];
|
||||
|
||||
for (var i = 0; i < itterationCount; i++)
|
||||
{
|
||||
var startTime = Environment.TickCount64;
|
||||
method.Invoke(classToInvokeMethodOn, parameters);
|
||||
var endTime = Environment.TickCount64;
|
||||
resultCollection[i] = new SingleTestResult(TimeSpan.FromMilliseconds(endTime - startTime));
|
||||
}
|
||||
|
||||
return resultCollection;
|
||||
}
|
||||
|
||||
private static void InvokeParses(SingleBenchmarkResult benchmarkResult, IResultParser[] Parsers, ILogger logger)
|
||||
{
|
||||
if (benchmarkResult.MethodResults.Length == 0)
|
||||
{
|
||||
logger?.LogWarning($"No result found from {benchmarkResult.ClassName} class.");
|
||||
}
|
||||
|
||||
foreach (var parser in Parsers)
|
||||
{
|
||||
parser.Parse(benchmarkResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using nanoFramework.Benchmark.Parser;
|
||||
using nanoFramework.Benchmark.Result;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace nanoFramework.Benchmark.Helpers
|
||||
{
|
||||
internal static class ArrayListHelper
|
||||
{
|
||||
internal static MethodResult[] ConvertFromArrayListToMethodResultArray(ArrayList arrayList)
|
||||
{
|
||||
var result = new MethodResult[arrayList.Count];
|
||||
for (int i = 0; i < arrayList.Count; i++)
|
||||
{
|
||||
result[i] = (MethodResult)arrayList[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static MethodInfo[] ConvertFromArrayListToMethodInfoArray(ArrayList arrayList)
|
||||
{
|
||||
var result = new MethodInfo[arrayList.Count];
|
||||
for (int i = 0; i < arrayList.Count; i++)
|
||||
{
|
||||
result[i] = (MethodInfo)arrayList[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static IResultParser[] ConvertFromArrayListToIResultParserArray(ArrayList arrayList)
|
||||
{
|
||||
var result = new IResultParser[arrayList.Count];
|
||||
for (int i = 0; i < arrayList.Count; i++)
|
||||
{
|
||||
result[i] = (IResultParser)arrayList[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace nanoFramework.Benchmark.Helpers
|
||||
{
|
||||
internal static class ReflectionHelpers
|
||||
{
|
||||
private static string[] ExcludedMethodsFromBenchmarks =
|
||||
{
|
||||
"ToString",
|
||||
"GetType",
|
||||
"GetHashCode"
|
||||
};
|
||||
|
||||
internal static object CreateObjectViaReflection(Type typeToCreate)
|
||||
{
|
||||
// Empty array of Types - GetConstructor didn't work unless given an empty array of Type[]
|
||||
Type[] types = { };
|
||||
|
||||
var ci = typeToCreate.GetConstructor(types);
|
||||
|
||||
if (ci == null)
|
||||
{
|
||||
// failed to create target instance
|
||||
return null;
|
||||
}
|
||||
|
||||
return ci.Invoke(null);
|
||||
}
|
||||
|
||||
internal static object GetSetupMethodIfExists(MethodInfo[] methods)
|
||||
{
|
||||
foreach (var item in methods)
|
||||
{
|
||||
if (GetFirstOrDefaultAttribute(item, typeof(SetupAttribute)) != null)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static object GetFirstAttribute(MemberInfo member, Type attributeType)
|
||||
{
|
||||
var attribute = GetFirstOrDefaultAttribute(member, attributeType);
|
||||
if (attribute == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
internal static object GetFirstOrDefaultAttribute(MemberInfo member, Type attributeType)
|
||||
{
|
||||
if (attributeType == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
if (!attributeType.IsSubclassOf(typeof(Attribute)))
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
if (member == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
var attribs = member.GetCustomAttributes(false);
|
||||
foreach (var item in attribs)
|
||||
{
|
||||
var itemType = item.GetType();
|
||||
if (itemType == attributeType)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
if (itemType.IsSubclassOf(attributeType))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static bool IsMethodProperty(MethodInfo method)
|
||||
{
|
||||
if (method.ReturnType != null && method.Name.StartsWith("get_"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (method.ReturnType == null && method.Name.StartsWith("set_"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsMethodExcluded(MethodInfo method)
|
||||
{
|
||||
if (IsMethodProperty(method))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ExcludedMethodsFromBenchmarks.Contains(method.Name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var setupAttribute = GetFirstOrDefaultAttribute(method, typeof(SetupAttribute));
|
||||
if (setupAttribute != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static MethodInfo[] GetBenchmarkMethods(MethodInfo[] methodInfos, ILogger logger)
|
||||
{
|
||||
var returnList = new ArrayList();
|
||||
foreach (var method in methodInfos)
|
||||
{
|
||||
if (IsMethodExcluded(method))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var benchmarkAttrib = GetFirstOrDefaultAttribute(method, typeof(BenchmarkAttribute));
|
||||
if (benchmarkAttrib == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var parameters = method.GetParameters();
|
||||
if (parameters.Length != 0)
|
||||
{
|
||||
logger?.LogWarning($"Skippping {method.Name} due to invalid parameters count. Benchmark methods should contains 0 parameters.");
|
||||
continue;
|
||||
}
|
||||
|
||||
returnList.Add(method);
|
||||
}
|
||||
|
||||
return ArrayListHelper.ConvertFromArrayListToMethodInfoArray(returnList);
|
||||
}
|
||||
|
||||
internal static object GetObjectInstanceFromPropertyIfExists(object classObject, Type typeToGet)
|
||||
{
|
||||
var allMethods = classObject.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (var method in allMethods)
|
||||
{
|
||||
if (!method.Name.StartsWith("get_"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.ReturnType != typeToGet)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return method.Invoke(classObject, new object[0]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static object GetObjectInstanceFromAttributesIfExists(Type classType, Type typeToGet)
|
||||
{
|
||||
var attribs = classType.GetCustomAttributes(false);
|
||||
foreach (var attrib in attribs)
|
||||
{
|
||||
var foundObject = GetObjectInstanceFromPropertyIfExists(attrib, typeToGet);
|
||||
if (foundObject != null)
|
||||
{
|
||||
return foundObject;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static ArrayList GetObjectsInstanceFromAttributesIfExists(Type classType, Type typeToGet)
|
||||
{
|
||||
var attribs = classType.GetCustomAttributes(false);
|
||||
var returnList = new ArrayList();
|
||||
foreach (var attrib in attribs)
|
||||
{
|
||||
var foundObject = GetObjectInstanceFromPropertyIfExists(attrib, typeToGet);
|
||||
if (foundObject != null)
|
||||
{
|
||||
returnList.Add(foundObject);
|
||||
}
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using nanoFramework.Benchmark.Attributes;
|
||||
using nanoFramework.Benchmark.Parser;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace nanoFramework.Benchmark.Helpers
|
||||
{
|
||||
internal class SettingsHelper
|
||||
{
|
||||
private static IResultParser[] defaultParsers;
|
||||
private static IResultParser[] DefaultParsers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (defaultParsers == null)
|
||||
{
|
||||
defaultParsers = new IResultParser[]
|
||||
{
|
||||
new ConsoleParser()
|
||||
};
|
||||
}
|
||||
|
||||
return defaultParsers;
|
||||
}
|
||||
}
|
||||
internal static ILogger GetLoggerIfExists(Type classType)
|
||||
{
|
||||
return (ILogger)ReflectionHelpers.GetObjectInstanceFromAttributesIfExists(classType, typeof(ILogger));
|
||||
}
|
||||
|
||||
internal static int GetItterationCount(Type benchmarkClass)
|
||||
{
|
||||
var attribute = ReflectionHelpers.GetFirstOrDefaultAttribute(benchmarkClass, typeof(ItterationCountAttribute));
|
||||
if (attribute != null && attribute is ItterationCountAttribute itterationCountAttribute)
|
||||
{
|
||||
return itterationCountAttribute.Count;
|
||||
}
|
||||
|
||||
return ItterationCountAttribute.DefaultItterationCount;
|
||||
}
|
||||
|
||||
internal static IResultParser[] GetResultParser(Type classType)
|
||||
{
|
||||
var parsers = ReflectionHelpers.GetObjectsInstanceFromAttributesIfExists(classType, typeof(IResultParser));
|
||||
if (parsers != null && parsers.Count != 0)
|
||||
{
|
||||
return ArrayListHelper.ConvertFromArrayListToIResultParserArray(parsers);
|
||||
}
|
||||
|
||||
return DefaultParsers;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Helpers
|
||||
{
|
||||
internal static class StringArrayExtensions
|
||||
{
|
||||
internal static bool Contains(this string[] array, string item)
|
||||
{
|
||||
foreach (var arrayItem in array)
|
||||
{
|
||||
if (arrayItem == item)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using nanoFramework.Benchmark.Helpers;
|
||||
using nanoFramework.Benchmark.Result;
|
||||
using nanoFramework.Benchmark.Result.Attributes;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Benchmark.Parser.Abstract
|
||||
{
|
||||
internal abstract class BaseTextParser : IResultParser
|
||||
{
|
||||
protected abstract string GetParserName(SingleBenchmarkResult benchmarkResult);
|
||||
protected abstract string GetHeader(MethodInfo[] dataToDisplay);
|
||||
protected abstract string GetRow(SingleBenchmarkResult item, MethodInfo[] dataToDisplay, int rowIndex);
|
||||
|
||||
protected virtual void PrintLine(string value)
|
||||
{
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
|
||||
protected static string GetHeaderFromAttribute(MethodInfo methodInfo)
|
||||
{
|
||||
// At this point all passed MethodsInfo should be properties and should have Display attribute
|
||||
return ((DisplayAttribute)ReflectionHelpers.GetFirstAttribute(methodInfo, typeof(DisplayAttribute))).Header;
|
||||
}
|
||||
|
||||
protected static string PadRight(string value, int toLenght)
|
||||
{
|
||||
var builder = new StringBuilder(value);
|
||||
for (int j = 0; j < toLenght - value.Length; j++)
|
||||
{
|
||||
builder.Append(" ");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
protected string GetDataFromDataMethod(SingleBenchmarkResult item, MethodInfo dataMethod, int rowIndex)
|
||||
{
|
||||
var parameters = GetParametersForDataMethod(dataMethod, rowIndex);
|
||||
return (string)dataMethod.Invoke(item, parameters);
|
||||
}
|
||||
|
||||
protected static object[] GetParametersForDataMethod(MethodInfo dataMethod, int rowIndex)
|
||||
{
|
||||
var parametersCount = dataMethod.GetParameters().Length;
|
||||
if (parametersCount == 0)
|
||||
{
|
||||
return new object[0];
|
||||
}
|
||||
|
||||
if (parametersCount == 1)
|
||||
{
|
||||
return new object[] { rowIndex };
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public virtual void Parse(SingleBenchmarkResult benchmarkResult)
|
||||
{
|
||||
PrintLine(string.Empty);
|
||||
PrintLine(string.Empty);
|
||||
PrintLine(GetParserName(benchmarkResult));
|
||||
|
||||
var dataToDisplay = SingleBenchmarkResult.GetDataToDisplay();
|
||||
PrintLine(GetHeader(dataToDisplay));
|
||||
|
||||
for (int i = 0; i < benchmarkResult.MethodResults.Length; i++)
|
||||
{
|
||||
PrintLine(GetRow(benchmarkResult, dataToDisplay, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using nanoFramework.Benchmark.Parser.Abstract;
|
||||
using nanoFramework.Benchmark.Result;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Benchmark.Parser
|
||||
{
|
||||
internal class ConsoleParser : BaseTextParser, IResultParser
|
||||
{
|
||||
private const string ConsoleTableSeparator = "|";
|
||||
private object lockObject = new();
|
||||
private int[] columnsSize;
|
||||
public override void Parse(SingleBenchmarkResult benchmarkResult)
|
||||
{
|
||||
lock (lockObject)
|
||||
{
|
||||
columnsSize = CalculateColumnSize(benchmarkResult);
|
||||
base.Parse(benchmarkResult);
|
||||
}
|
||||
}
|
||||
|
||||
private int[] CalculateColumnSize(SingleBenchmarkResult benchmarkResult)
|
||||
{
|
||||
var dataToDisplay = SingleBenchmarkResult.GetDataToDisplay();
|
||||
int[] columnSizes = new int[dataToDisplay.Length];
|
||||
for (int i = 0; i < dataToDisplay.Length; i++)
|
||||
{
|
||||
var column = dataToDisplay[i];
|
||||
var header = GetHeaderFromAttribute(column);
|
||||
columnSizes[i] = CalculateColumnSize(column, header, benchmarkResult);
|
||||
}
|
||||
|
||||
return columnSizes;
|
||||
}
|
||||
|
||||
private static int CalculateColumnSize(MethodInfo method, string header, SingleBenchmarkResult benchmarkResult)
|
||||
{
|
||||
var size = header.Length;
|
||||
for (int i = 0; i < benchmarkResult.MethodResults.Length; i++)
|
||||
{
|
||||
var parameters = GetParametersForDataMethod(method, i);
|
||||
var value = (string)method.Invoke(benchmarkResult, parameters);
|
||||
if (value.Length > size)
|
||||
{
|
||||
size = value.Length;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
protected override string GetParserName(SingleBenchmarkResult benchmarkResult)
|
||||
{
|
||||
return $"Console export: {benchmarkResult.ClassName} benchmark class.";
|
||||
}
|
||||
|
||||
protected override string GetHeader(MethodInfo[] dataToDisplay)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
stringBuilder.Append($"{ConsoleTableSeparator}");
|
||||
for (int i = 0; i < dataToDisplay.Length; i++)
|
||||
{
|
||||
var item = dataToDisplay[i];
|
||||
var header = GetHeaderFromAttribute(item);
|
||||
stringBuilder.Append(" ");
|
||||
stringBuilder.Append(PadRight(header, columnsSize[i]));
|
||||
stringBuilder.Append($" {ConsoleTableSeparator}");
|
||||
}
|
||||
|
||||
// Create row after header, seperating rows and headers
|
||||
var headerLength = stringBuilder.Length;
|
||||
stringBuilder.AppendLine();
|
||||
stringBuilder.Append($"{ConsoleTableSeparator} ");
|
||||
// -4 characters = '| ' + ' |'
|
||||
for (int i = 0; i < headerLength - 4; i++)
|
||||
{
|
||||
stringBuilder.Append("-");
|
||||
}
|
||||
stringBuilder.Append($" {ConsoleTableSeparator}");
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
protected override string GetRow(SingleBenchmarkResult item, MethodInfo[] dataToDisplay, int rowIndex)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
stringBuilder.Append($"{ConsoleTableSeparator}");
|
||||
for (int i = 0; i < dataToDisplay.Length; i++)
|
||||
{
|
||||
var dataMethod = dataToDisplay[i];
|
||||
var rowData = GetDataFromDataMethod(item, dataMethod, rowIndex);
|
||||
stringBuilder.Append($" ");
|
||||
stringBuilder.Append(PadRight(rowData, columnsSize[i]));
|
||||
stringBuilder.Append($" {ConsoleTableSeparator}");
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
using nanoFramework.Benchmark.Parser.Abstract;
|
||||
using nanoFramework.Benchmark.Result;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace nanoFramework.Benchmark.Parser
|
||||
{
|
||||
internal class CsvParser : BaseTextParser, IResultParser
|
||||
{
|
||||
private const char ValuesSeparator = ';';
|
||||
|
||||
protected override string GetParserName(SingleBenchmarkResult benchmarkResult)
|
||||
{
|
||||
return $"CSV export: {benchmarkResult.ClassName} benchmark class.";
|
||||
}
|
||||
|
||||
protected override string GetHeader(MethodInfo[] dataToDisplay)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < dataToDisplay.Length; i++)
|
||||
{
|
||||
var item = dataToDisplay[i];
|
||||
var header = GetHeaderFromAttribute(item);
|
||||
stringBuilder.Append(header);
|
||||
|
||||
if (i < dataToDisplay.Length - 1)
|
||||
{
|
||||
stringBuilder.Append($"{ValuesSeparator}");
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
protected override string GetRow(SingleBenchmarkResult item, MethodInfo[] dataToDisplay, int rowIndex)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < dataToDisplay.Length; i++)
|
||||
{
|
||||
var dataMethod = dataToDisplay[i];
|
||||
var rowData = GetDataFromDataMethod(item, dataMethod, rowIndex);
|
||||
stringBuilder.Append(rowData);
|
||||
|
||||
if (i < dataToDisplay.Length - 1)
|
||||
{
|
||||
stringBuilder.Append($"{ValuesSeparator}");
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using nanoFramework.Benchmark.Result;
|
||||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Parser
|
||||
{
|
||||
public interface IResultParser
|
||||
{
|
||||
void Parse(SingleBenchmarkResult benchmarkResult);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CSharp.TestApplication")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CSharp.TestApplication")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// This attribute is mandatory when building Interop libraries //
|
||||
// update this whenever the native assembly signature changes //
|
||||
[assembly: AssemblyNativeVersion("1.0.0.0")]
|
||||
/////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Result.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public sealed class DisplayAttribute : Attribute
|
||||
{
|
||||
public string Header { get; }
|
||||
|
||||
public DisplayAttribute(string header)
|
||||
{
|
||||
Header = header;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using nanoFramework.Benchmark.Helpers;
|
||||
using nanoFramework.Benchmark.Result.Attributes;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace nanoFramework.Benchmark.Result
|
||||
{
|
||||
public class MethodResult
|
||||
{
|
||||
private string _methodName;
|
||||
private string _meanExecutionTime;
|
||||
private string _maxExecutionTime;
|
||||
private string _minExecutionTime;
|
||||
|
||||
public SingleTestResult[] SingleTestResults { get; }
|
||||
|
||||
public MethodResult(string methodName, SingleTestResult[] singleTestResults)
|
||||
{
|
||||
_methodName = methodName;
|
||||
SingleTestResults = singleTestResults;
|
||||
}
|
||||
|
||||
internal string GetMethodName()
|
||||
{
|
||||
return _methodName;
|
||||
}
|
||||
|
||||
internal string GetMeanExecutionTime()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_meanExecutionTime))
|
||||
{
|
||||
long sumTicks = 0;
|
||||
int elemetsCount = 0;
|
||||
|
||||
foreach (var item in SingleTestResults)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sumTicks += item.ElapsedTime.Ticks;
|
||||
elemetsCount++;
|
||||
}
|
||||
|
||||
_meanExecutionTime = $"{TimeSpan.FromTicks(sumTicks / elemetsCount).TotalMilliseconds} ms";
|
||||
}
|
||||
|
||||
return _meanExecutionTime;
|
||||
}
|
||||
|
||||
internal string GetMinExecutionTime()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_minExecutionTime))
|
||||
{
|
||||
double minTime = double.MaxValue;
|
||||
foreach (var item in SingleTestResults)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.ElapsedTime.TotalMilliseconds < minTime)
|
||||
{
|
||||
minTime = item.ElapsedTime.TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
_minExecutionTime = $"{minTime:N0} ms";
|
||||
}
|
||||
|
||||
return _minExecutionTime;
|
||||
}
|
||||
|
||||
internal string GetMaxExecutionTime()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_maxExecutionTime))
|
||||
{
|
||||
double maxTime = 0;
|
||||
foreach (var item in SingleTestResults)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.ElapsedTime.TotalMilliseconds > maxTime)
|
||||
{
|
||||
maxTime = item.ElapsedTime.TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
_maxExecutionTime = $"{maxTime:N0} ms";
|
||||
}
|
||||
|
||||
return _maxExecutionTime;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
using nanoFramework.Benchmark.Helpers;
|
||||
using nanoFramework.Benchmark.Result.Attributes;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace nanoFramework.Benchmark.Result
|
||||
{
|
||||
public class SingleBenchmarkResult
|
||||
{
|
||||
public MethodResult[] MethodResults { get; }
|
||||
public string ClassName { get; }
|
||||
public int ItterationCount { get; }
|
||||
|
||||
public SingleBenchmarkResult(MethodResult[] methodResults, string className, int itterationCount)
|
||||
{
|
||||
MethodResults = methodResults;
|
||||
ClassName = className;
|
||||
ItterationCount = itterationCount;
|
||||
}
|
||||
|
||||
[Display("MethodName")]
|
||||
public string MethodName(int index)
|
||||
{
|
||||
return MethodResults[index].GetMethodName();
|
||||
}
|
||||
|
||||
[Display("ItterationCount")]
|
||||
public string ItterationCountMethod()
|
||||
{
|
||||
return ItterationCount.ToString();
|
||||
}
|
||||
|
||||
[Display("Mean")]
|
||||
public string MeanExecutionTime(int index)
|
||||
{
|
||||
return MethodResults[index].GetMeanExecutionTime();
|
||||
}
|
||||
|
||||
[Display("Max")]
|
||||
public string MaxExecutionTime(int index)
|
||||
{
|
||||
return MethodResults[index].GetMaxExecutionTime();
|
||||
}
|
||||
|
||||
[Display("Min")]
|
||||
public string MinExecutionTime(int index)
|
||||
{
|
||||
return MethodResults[index].GetMinExecutionTime();
|
||||
}
|
||||
|
||||
// TODO: Move to helper class
|
||||
internal static MethodInfo[] GetDataToDisplay()
|
||||
{
|
||||
var tempList = new ArrayList();
|
||||
var allMethods = typeof(SingleBenchmarkResult).GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (var method in allMethods)
|
||||
{
|
||||
var displayAttrib = ReflectionHelpers.GetFirstOrDefaultAttribute(method, typeof(DisplayAttribute));
|
||||
if (displayAttrib == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tempList.Add(method);
|
||||
}
|
||||
|
||||
return ArrayListHelper.ConvertFromArrayListToMethodInfoArray(tempList);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark.Result
|
||||
{
|
||||
public sealed class SingleTestResult
|
||||
{
|
||||
public TimeSpan ElapsedTime { get; }
|
||||
|
||||
public SingleTestResult(TimeSpan elapsedTime)
|
||||
{
|
||||
ElapsedTime = elapsedTime;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace nanoFramework.Benchmark
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class SetupAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectGuid>b2827cb3-4bcd-40c0-a82d-5ab476e84ce4</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<RootNamespace>nanoFramework.Benchmark</RootNamespace>
|
||||
<AssemblyName>nanoFramework.Benchmark</AssemblyName>
|
||||
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Attributes\Abstract\ParserAttribute.cs" />
|
||||
<Compile Include="Attributes\CsvParserAttribute.cs" />
|
||||
<Compile Include="Attributes\ConsoleParserAttribute.cs" />
|
||||
<Compile Include="BenchmarkAttribute.cs" />
|
||||
<Compile Include="BenchmarkRunner.cs" />
|
||||
<Compile Include="Attributes\DebugLoggerAttribute.cs" />
|
||||
<Compile Include="Helpers\ArrayListHelper.cs" />
|
||||
<Compile Include="Helpers\SettingsHelper.cs" />
|
||||
<Compile Include="Helpers\StringArrayExtensions.cs" />
|
||||
<Compile Include="Attributes\ItterationCountAttribute.cs" />
|
||||
<Compile Include="Attributes\Abstract\LoggerAttribute.cs" />
|
||||
<Compile Include="Parser\Abstract\BaseTextParser.cs" />
|
||||
<Compile Include="Parser\ConsoleParser.cs" />
|
||||
<Compile Include="Parser\CsvParser.cs" />
|
||||
<Compile Include="Parser\IResultParser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
||||
<Compile Include="Result\Attributes\DisplayAttribute.cs" />
|
||||
<Compile Include="Result\MethodResult.cs" />
|
||||
<Compile Include="Result\SingleBenchmarkResult.cs" />
|
||||
<Compile Include="Result\SingleTestResult.cs" />
|
||||
<Compile Include="SetupAttribute.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib">
|
||||
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Logging">
|
||||
<HintPath>..\packages\nanoFramework.Logging.1.1.2\lib\nanoFramework.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.Runtime.Native">
|
||||
<HintPath>..\packages\nanoFramework.Runtime.Native.1.5.4\lib\nanoFramework.Runtime.Native.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Collections">
|
||||
<HintPath>..\packages\nanoFramework.System.Collections.1.4.0\lib\nanoFramework.System.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nanoFramework.System.Text">
|
||||
<HintPath>..\packages\nanoFramework.System.Text.1.2.3\lib\nanoFramework.System.Text.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
|
||||
<ProjectExtensions>
|
||||
<ProjectCapabilities>
|
||||
<ProjectConfigurationsDeclaredAsItems />
|
||||
</ProjectCapabilities>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Logging" version="1.1.2" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.Runtime.Native" version="1.5.4" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Collections" version="1.4.0" targetFramework="netnano1.0" />
|
||||
<package id="nanoFramework.System.Text" version="1.2.3" targetFramework="netnano1.0" />
|
||||
</packages>
|
Загрузка…
Ссылка в новой задаче