Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
ManualConfig можно его выключить.[Params(1,2,3)] int X, то на каждое значение X будет собственный Baseline. Если вы хотите сравнивать A1 с A2, а B1 с B2 попарно, то нужно делать два отдельных класса. Группировку методов сделать не так сложно, но сложно сделать так, чтобы для общего случая результаты отображались бы так, чтобы всем было понятно, к чему какой Baseline-относится (если у вас есть хорошие идеи, то я их с радостью послушаю).IColumn по аналогии с BaselineDiffColumn и добавить в конфиг (кода нужно совсем немного, зато вы сможете заточить колонку под собственные нужды).[Params(Enumerable.Max, CustomClass.Max)]
public Func<int[], int> Max {get;set;}Очень удобно, когда функция показана в отдельном стобце, а не кодируется в названии метода LinqMax, CustomMax и т.п.
Max | Linq | 0.456347
Max | Custom | 1
Average | Linq | 0.784584
Average | Custom | 1А есть возможность сделать так, чтобы все методы были в интерфейсе, который реализуется в каждом из классов?
var summary = BenchmarkRunner.Run<BaseLineClass, Comp1Class, Comp2Class>();[Benchmark], в остальных классах ищутся соответствующие им (по названию, например) методы, после чего замеряются, причем вызов первого класса является эталонным, а остальные замеряются в пропорции к нему, как у вас уже сделано. Пример вывода выше: первичны функции, вторичны классы. То есть нужно наглядно сравнить, что вот ага, этот метод быстрее чем аналог в 10 раз, а вот этот медленнее в полтора раза, его надо пофиксить.params Type[], чтобы аналогично сколько угодно классов можно было сравнивать. В результате первые 3 это просто удобная обертка для последнего метода, который должен учесть, что есть N реализаций какого-то метода, причем не обязательно с одинаковой сигнатурой: например я сравниваю стандартный метод, который принимает Func<T, TResult>, а в моей реализации используется Expression<Func<T, TResult>>, соответственно нужно ориентироваться только на имя. Ну или можно еще атрибут навесить, с названием метода, которое должно быть уникальным в пределах класса и соответствовать именам тестируемых функций в соревнующихся классах. public class Benchmark_Method1
{
[Benchmark(Description="OldClass_Method1", BaseLine = true)]
public void OldClass_Method1()
{
new OldClass().Method1();
}
[Benchmark(Description="NewClass_Method1")]
public void NewClass_Method1()
{
new NewClass().Method1();
}
}
// Тут еще 9 похожих классов
[TestClass]
public class Benchmarks
{
[TestMethod]
public void TestMethod1()
{
BenchmarkRunner.Run<Benchmark_Method1>();
}
[TestMethod]
public void TestMethod2()
{
BenchmarkRunner.Run<Benchmark_Method2>();
}
// Тут еще 8 похожих тестов
} [TestMethod]
public void TestMethod1()
{
Summary result1 = BenchmarkRunner.Run<Benchmark_Method1>();
Summary result2 = BenchmarkRunner.Run<Benchmark_Method2>();
...
Console.WriteLine(ExtractInfoFromSummary(result1));
Console.WriteLine(ExtractInfoFromSummary(result2));
...
}Пока что простого путя для дебага нет: если возникли проблемы, то нужно открыть сгенерированный проект и дебажить его. Ну или вызвать проблемный метод в основной программе руками. Хотим в дальнейшем упростить дебаг, но в общем случае вспомогательные проекты всё равно будут генерироваться, собираться и запускаться: без этого не сделать сравнение разных окружений (и много других проблем появится).
namespace LoadTest
{
class Program
{
static void Main(string[] args)
{
TestMethod1();
//Console.WriteLine("Hello World!");
Console.ReadLine();
}
public static void TestMethod1()
{
var result1 = BenchmarkRunner.Run<TheEasiestBenchmark>();
Console.WriteLine(result1);
}
}
public class TheEasiestBenchmark
{
[Benchmark(Description = "Summ100")]
public int Test100()
{
return Enumerable.Range(1, 100).Sum();
}
[Benchmark(Description = "Summ200")]
public int Test200()
{
return Enumerable.Range(1, 200).Sum();
}
}
}
Замеряем производительность с помощью BenchmarkDotNet