Closed russcam closed 7 years ago
As a person that is responsible for .NET Core support in BechmarkDotNet project I am very happy to see people using it. Please do not hesitate to ask any questions, I will do my best to solve any upcoming issues.
@russcam I have commented your question in our issues list, please take a look. I think that we already have what you need, except that you will have to install dotnet cli toolchain on the machines that you would like to run your benchmarks.
Btw soon we should have a possibility to run single Benchmark for multiple runtimes so you could compare your performance for all supported frameworks in one place (Classic Clr, Dnx451, .NET Core)
Both BenchmarkDotNet and NBench expose collection of GC and memory allocation stats. Are there other metrics that we might be interested in capturing through e.g. performance counters, event tracing?
I've done most of the work on "diagnostics" in BenchmarkDotNet. For reference we already use ETW to capture memory allocations and we plan to have performance counter support soon (ish!). Please feel free to add a comment to an existing issue or create a new one for anything else that you would need.
Thanks @adamsitnik and @mattwarren! This was a very rough brain dump of thoughts on benchmarking and profiling for discussion.
I'll be sure to reach out if we come up with other ideas :+1:
This issue aims to discuss our approach to benchmarking and profiling for the purpose of being able to track the performance of the clients as the source is iterated upon.
Definitions
Firstly, some clarfication on what we mean by Benchmarking and Profiling:
Benchmarking
Benchmarking is the process of measuring the performance of a program by getting it to process some task and measuring how long it takes.
The fundamental reason for benchmarking is to be able to identify when a change has made the program run slower. It also allows us to have some rough metrics for expected throughput for a given environment.
Profiling
Profiling is used to identify the parts of a program which take the most time and sometimes, the most memory.
Performance in the context of profiling is relative only to the components that make up the program; that is, the part of a program that takes the most time may not be the slowest part of a process in which the program is used. For example, in the case of NEST, the json serializer may be the slowest part of the client but the time taken by serializer could be insignificant in comparison to the latency of making a HTTP request.
Both Benchmarking and Profiling are important; the former to understand as a whole where performance has changed within the client and the latter, to understand where the time/memory bottlenecks within the client could be improved.
Approach
Benchmarking
There are a number of projects in the .NET space that have sprung up around Benchmarking; the two that look to be showing the most promise are
BenchmarkDotNet is a low level library for performance testing a piece of code; the code to be executed is placed within a
[Benchmark]
attributed method, optionally with two other methods to perform setup and teardown for the benchmark. BenchmarkDotNet takes the source of the method and generates a separate isolated executable in which to benchmark the running of the method. This is performed for every method to be benchmarked.NBench is a higher level library for performing benchmarking that internally uses BenchmarkDotNet. The intention with NBench is to be able to write benchmarking unit tests to make assertions about program performance, in addition to being able to collecting metrics as per BenchmarkDotNet
Goals
What do we want to get out of benchmarking? Obviously we want to record performance metrics of the client, but there are a number of areas for discussion:
Do we want to benchmark all methods or a meaningful subset?
My initial thoughts here are that we should look at benchmarking the most travelled paths to begin:
Elasticsearch cluster configuration
It might make sense to use the same configuration as is used for the Elasticsearch nightly benchmarks
Collecting other metrics
Both BenchmarkDotNet and NBench expose collection of GC and memory allocation stats. Are there other metrics that we might be interested in capturing through e.g. performance counters, event tracing?
Ability to run from the command line
So that we can set up our CI environment to run benchmarks nightly/on each checkin/on each release.
Use our existing Tests project
It would be ideal if we could use the existing suite of integration tests for benchmarking purposes, avoiding the overhead in maintaining another suite of tests.
Plot/Illustrate performance over time
Visualizing performance would provide an easy way to determine and investigate any issues that may occur.
Challenges
So far
The feature/profiling-benchmarkdotnet branch has a POC for benchmarking using BenchmarkDotNet. This is an alpha to get it running against the dnx build of the solution, which is incomplete for Core CLR due to challenge 1 above.
The feature/profiling-nbench branch has a POC for benchmarking using NBench. This builds the non-DNX solution using MSBuild to produce a .NET 4.5 compatible version of NEST.
Profiling
A number of tools are available for profiling
Only the last tool is free for commercial use.
Goals
Persist Profile snapshots over time
Record profile snapshots for components of the client to be able to determine
Ability to Diff snapshots
So we can quickly determine where performance may have got better (or worse)
Ability to run from the command line and IDE
So that we can set up our CI environment to run profiling nightly/on each checkin/on each release, as well as be able to profile ad-hoc within the IDE when the need arises.
Use our existing Tests project
It would be ideal if we could use the existing suite of integration tests for profiling purposes, avoiding the overhead in maintaining another suite of tests.
Since we would need some task to process in order to perform profiling, we could use the benchmarking components for profiling purposes.
Plot/Illustrate performance profiles over time
Same as for benchmarking
Challenges
I have experience with both DotTrace and ANTS which makes me lean towards using one of those for profiling purposes and, since I already have a JetBrains license, this makes using DotTrace more compelling.
So far
The feature/profiling branch has a POC for profiling using DotTrace's Self Profiling API. The intention with the setup in the branch have is to be able to attribute types in the Tests project with different attributes to run performance and timeline profiling; The Profiling project simply being a shell for running the profiler by
[Performance]
and[Timeline]
attributes in the Tests project via Reflection.The profile snapshots would be saved into separate files as this should make it easier to understand where performance may have changed over time, based on knowing which method a snapshot relates to.
This setup has intermittently worked in the past but now when attaching the profiler, the profiler never becomes active; It looks like JetBrains are looking into this issue but thet have also just released a new version of DotTrace (2016.1) that should be tried.