Self-hosted service
dotnet/crank avatar
dotnet/crank

Crank is the benchmarking rig the .NET team uses on its own frameworks

Benchmarking infrastructure for applications

1,083 stars111 forksC#MIT

At a glance

What is it?
Crank is MIT licensed benchmarking infrastructure from the .NET team, built to deploy and measure multi-tiered applications from .NET or Docker containers, store results in JSON or SQL Server for charting, and collect traces. It runs the TechEmpower web framework scenarios, and it ships three HTTP load generators, two of which only work on Linux.
Who is it for?
Crank suits a .NET performance engineer who has to compare frameworks or framework versions reproducibly, who needs more than a load generator pointed at a URL, and who can host an agent machine. It does not suit a quick single endpoint check, where a load generator and a stopwatch are enough, and it is a poor fit for a team without Linux available, since wrk and wrk2 are the tools the TechEmpower scenarios are written against.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The benchmarking infrastructure behind the .NET numbers

Crank is the benchmarking infrastructure used by the .NET team to run benchmarks, including, but not limited to, scenarios from the TechEmpower Web Framework Benchmarks. That context explains almost everything about the shape of the tool.

A public benchmark has a specific problem: several implementations written by different teams, in different languages, have to be run under comparable conditions so the comparison is fair. That means each application has to be deployed, configured, warmed up, loaded, measured and torn down in a repeatable way, and the results have to land somewhere they can be charted. A load generator alone does not solve any of that.

The stated goal is to give developers a tool that lets them work on performance and measure potential improvements very easily, and the listed capabilities follow from it. You can deploy and benchmark multi-tiered applications based on .NET or Docker containers. You can store results in JSON or in SQL Server for charting. You can customize the applications or their environment to test different settings. And you can collect traces.

The audience is therefore a performance engineer inside an organisation that ships a server framework or a large service, and the difference from a one-off measurement is the repeatability. A benchmark that cannot be reproduced is an anecdote, and Crank's job is to make the whole sequence, from the deployment to the chart, a declarative thing that a team can run again.

It is MIT licensed, the repository is not archived, and the last push was on 2026-10-15. There are no GitHub releases, so the version you install comes from the tool packaging rather than a release page.

A controller, an agent, and jobs in between

The infrastructure is made of two components, and the split tells you how a benchmark run is organised.

crank-agent is a service that executes the jobs that run as part of a benchmark. crank is a command line utility that can enqueue jobs and record results. So the controller does not run the load, it queues work, and the agent does the work on the machine where the application is running.

That is the difference between Crank and a load generator, and it is the reason multi-tiered scenarios are possible. The controller can sit on a laptop while the agent runs on a benchmark host, and the agent is what deploys the application, starts the processes and reports back. It also means the agent host is where the interesting constraints live, since that is the machine whose CPU, memory and network the measurement describes.

The repository layout is consistent with a two-part tool plus a set of jobs. Under src/ there are the components, with the agent and the controller in their own projects, and the built in jobs each in their own project, and there is a solution file, Microsoft.Crank.sln, tying them together. The samples/ directory holds the worked examples, with hello, local, micro, netty, post, precommand and scripts, and the scripts sample in particular suggests a way to run arbitrary commands as part of a scenario.

The engine directory, eng/, and the build entry points build.sh and build.cmd, along with the Azure Pipelines definitions, are the pieces that turn that into something a team can run in CI without hand assembly.

Three load generators, and two of them need Linux

Crank ships with built in jobs that are HTTP client benchmarking tools, and this is the part with a hard platform constraint.

wrk is described as an http client benchmarking tool used when benchmarking TechEmpower, and it is Linux only. wrk2 is another http client benchmarking tool, optimised for latency testing, and it is also Linux only. bombardier is a Go based http client benchmarking tool and it is cross-platform.

That distinction has direct consequences. The TechEmpower scenarios are written against wrk, and wrk and wrk2 are the tools used for the classic latency versus throughput measurements, so reproducing a published TechEmpower number means running on Linux with those jobs. On Windows or macOS, the built in option is bombardier, which is a different generator with different characteristics, and results are not directly comparable to a published figure produced with wrk.

So the platform requirement is not a preference, it is part of the measurement definition. A team benchmarking on a laptop, where the load generator competes with the application for the same CPU, is also measuring something else entirely, which is the reason the agent exists as a separate service in the first place.

The three tools cover different needs rather than duplicating each other: a throughput oriented generator, a latency oriented one, and a portable one for cross platform use.

Results land in JSON or SQL Server, and traces come along

Storing results is a first class feature rather than a printing exercise. Crank can store results in JSON or in SQL Server for charting, and the SQL Server path is the one that matters for a team that wants a history.

The distinction is about the shape of the workflow. JSON output is a file you can diff, commit to a repository or post into a pipeline, and it is the right choice for a one-off run or a reproducible experiment. A database is the right choice when the questions are comparative over time, because it is what turns a series of runs into a trend, and it is what lets a chart answer whether a change helped.

The collection of traces is the other half of the output story. A throughput number tells you that something regressed, and a trace tells you where the time went. Running both against the same scenario is what makes the tool useful for the person who has to fix the regression rather than just report it.

The environment is configurable too, since Crank lets you customize the applications or their environment to test different settings. That is the feature that distinguishes the tool from a benchmark script, because it is what lets you compare a configuration rather than only a version. The samples directory reinforces this, with a local sample, a micro sample and a precommand sample, which are the kinds of pieces a scenario composes together.

Getting started means three things in the README

The Get Started section is short, and each item is a prerequisite rather than a step.

First, install the .NET 10 SDK to build and run Crank, with the note that benchmark applications can target other .NET versions. That is the key point about the SDK requirement: it is the toolchain for Crank itself, not a constraint on what you benchmark, so a team can keep a service on an older framework and still measure it.

Second, read the documentation, which lives in docs/ in the repository and has its own README.

Third, install the controller as a dotnet tool:

bash
dotnet tool update Microsoft.Crank.Controller --version "0.2.0-*" --global

The version argument uses a wildcard on a prerelease series, which tells you something about how the tool is distributed: the controller is versioned and shipped as a global tool, and the 0.2.0 prerelease line is the one the README points at. Since the repository has no GitHub releases, the tool feed is the practical place to see what exists.

Fourth, and this is the one that saves the most time, use the predefined scenarios from the aspnet/Benchmarks repository. Writing a scenario from scratch means learning the file format, the job definitions, the application definitions and how results are named, and the TechEmpower derived scenarios are a working reference for all of it.

A realistic first run is therefore: install the SDK, install the controller, take a scenario from the aspnet repository, point it at an application you control, and read the JSON output before you try to make the charts work.

Daily builds, a low-spam announcement issue, and the pipelines behind it

The engagement section is short and tells you how the project runs.

For following the project, the recommended route is to subscribe to a specific issue used to post announcements, with the note that only team members can post on it. The framing is a low-spam way to follow what the team is doing, which is a reasonable choice for a project that would otherwise post a stream of build notifications.

The contribution routes are the usual ones, trying things out, filing issues, joining design conversations and making pull requests, and the README points at the contributing page for the best places to log issues and start discussions. The project also offers daily builds, and there is a Contributing note about downloading the latest daily builds and trying the tutorials with your own projects.

The repository reflects a continuous integration setup rather than a release based one. There are three pipeline definitions at the top level, azure-pipelines.yml, azure-pr-pipelines.yml and azure-pipelines-release.yml, a .azuredevops/ directory, and the .nuget/ directory alongside a NuGet.config for the packages. The code of conduct is the Contributor Covenant as adopted by the .NET Foundation, and the LICENSE.txt and NOTICE.txt are both present, which is the convention for a project that vendors or derives from other work.

The engineering scaffolding is also visible in the build files, with Directory.Build.props, Directory.Build.targets, Directory.Packages.props for central package version management, global.json pinning the SDK, an .editorconfig and .gitattributes, and an es-metadata.yml, which is where EventSource metadata lives, and that is consistent with a tool that collects traces.

Editorial conclusion

Crank suits a .NET performance engineer who has to compare frameworks or framework versions reproducibly, who needs more than a load generator pointed at a URL, and who can host an agent machine. It does not suit a quick single endpoint check, where a load generator and a stopwatch are enough, and it is a poor fit for a team without Linux available, since wrk and wrk2 are the tools the TechEmpower scenarios are written against. Verify first which load generator your scenario references, since the Linux only entries will not run elsewhere and bombardier is the cross-platform option, and expect to learn the scenario file format from the documentation in docs/ rather than from the README.

Frequently asked questions

What is Crank used for?

Crank is the benchmarking infrastructure the .NET team uses to run benchmarks, including scenarios from the TechEmpower Web Framework Benchmarks. It deploys and benchmarks multi-tiered applications based on .NET or Docker containers, stores results in JSON or SQL Server for charting, customises applications and their environment, and collects traces.

What are the two components of Crank?

crank-agent is a service that executes the jobs that run as part of a benchmark, and crank is a command line utility that enqueues jobs and records results. The controller queues the work and the agent runs it on the machine hosting the application.

Which HTTP load generators does Crank include and what are their platform limits?

wrk and wrk2 are Linux only, with wrk used for the TechEmpower benchmarks and wrk2 optimised for latency testing. bombardier is Go based and cross-platform.

How do I install the Crank controller?

As a global dotnet tool with dotnet tool update Microsoft.Crank.Controller --version "0.2.0-*" --global, after installing the .NET 10 SDK to build and run Crank. Benchmark applications themselves can target other .NET versions.

Where should I store benchmark results, JSON or SQL Server?

Both are supported. JSON suits a one-off run or a file you want to diff and keep in a repository, while SQL Server is the option for charting and for comparing a series of runs over time.

Official sources

  1. dotnet/crank on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dotnet-crank.svg)](https://hysenlabs.com/projects/dotnet-crank)

Was this useful?