Convert Figma logo to code with AI

fcsonline logodrill

Drill is an HTTP load testing application written in Rust

2,077
109
2,077
55

Top Related Projects

Fast cross-platform HTTP benchmarking tool written in Go

23,459

HTTP load testing tool and library. It's over 9000!

37,830

Modern HTTP benchmarking tool

18,056

HTTP load generator, ApacheBench (ab) replacement

4,261

A constant throughput, correct latency recording variant of wrk

24,772

Write scalable load tests in plain Python 🚗💨

Quick Overview

Drill is an HTTP load testing application written in Rust. It's inspired by Ansible syntax and designed to be easy to use, providing a way to perform complex load testing scenarios with a simple YAML configuration file.

Pros

  • Easy to use with a simple YAML configuration
  • Supports complex load testing scenarios
  • Written in Rust, offering high performance
  • Provides detailed statistics and reporting

Cons

  • Limited documentation compared to some other load testing tools
  • Fewer features compared to more established tools like Apache JMeter
  • Requires Rust knowledge for advanced customization or contribution

Getting Started

To get started with Drill:

  1. Install Rust and Cargo (Rust's package manager)
  2. Install Drill:
    cargo install drill
    
  3. Create a YAML file (e.g., benchmark.yml) with your test plan:
    ---
    concurrency: 4
    base: 'http://localhost:9000'
    iterations: 10
    
    plan:
      - name: Fetch users
        request:
          url: /api/users
    
  4. Run the test:
    drill --benchmark benchmark.yml --stats
    

This will execute the defined test plan, making 10 requests to the specified endpoint with 4 concurrent users, and display statistics about the test run.

Competitor Comparisons

Fast cross-platform HTTP benchmarking tool written in Go

Pros of Bombardier

  • Written in Go, potentially offering better performance and cross-platform compatibility
  • Supports HTTP/1.1 and HTTP/2 protocols
  • Provides more detailed statistics and percentiles in the output

Cons of Bombardier

  • Less flexible in terms of request customization compared to Drill
  • Lacks support for custom plugins or extensions
  • May have a steeper learning curve for users familiar with YAML-based configuration

Code Comparison

Drill (YAML configuration):

plan:
  - name: Search for keywords
    request:
      url: https://api.example.com/search
      method: POST
      body: '{"query": "performance testing"}'

Bombardier (Command-line usage):

bombardier -c 100 -n 10000 -m POST -H "Content-Type: application/json" \
  -b '{"query": "performance testing"}' https://api.example.com/search

Both tools allow for specifying HTTP methods, headers, and request bodies, but Drill's YAML configuration may be more readable for complex scenarios, while Bombardier's command-line approach offers quick setup for simpler tests.

23,459

HTTP load testing tool and library. It's over 9000!

Pros of Vegeta

  • Written in Go, offering better performance and concurrency handling
  • More mature project with a larger community and ecosystem
  • Supports multiple output formats (JSON, CSV, Histogram)

Cons of Vegeta

  • Less intuitive syntax for complex scenarios compared to Drill's YAML
  • Limited built-in support for dynamic data generation
  • Steeper learning curve for users not familiar with Go

Code Comparison

Vegeta:

echo "GET http://example.com" | vegeta attack -duration=5s | vegeta report

Drill:

---
concurrency: 4
base: 'http://example.com'
iterations: 10

plan:
  - name: Fetch users
    request:
      url: /api/users

Key Differences

  • Drill uses YAML for test configuration, making it more readable for complex scenarios
  • Vegeta offers a command-line interface for quick tests, while Drill requires a config file
  • Drill provides built-in support for iterations and concurrency settings in its config
  • Vegeta excels in raw performance and scalability for high-load testing
  • Drill offers more intuitive syntax for chaining requests and handling dynamic data

Both tools are valuable for load testing, with Vegeta being more suitable for high-performance scenarios and Drill offering easier configuration for complex test cases.

37,830

Modern HTTP benchmarking tool

Pros of wrk

  • Written in C, offering high performance and low resource usage
  • Simple command-line interface for quick benchmarking
  • Supports Lua scripting for more advanced request generation

Cons of wrk

  • Limited built-in reporting capabilities
  • Less focus on API testing and complex scenarios
  • Steeper learning curve for advanced usage with Lua scripting

Code Comparison

wrk:

wrk.method = "POST"
wrk.body   = '{"foo": "bar"}'
wrk.headers["Content-Type"] = "application/json"

drill:

- name: Create user
  request:
    url: /api/users
    method: POST
    body: '{"name": "John", "email": "john@example.com"}'
    headers:
      Content-Type: application/json

Key Differences

  • wrk is primarily a HTTP benchmarking tool, while drill focuses on API testing and load testing
  • drill uses YAML for test configuration, making it more readable and easier to maintain for complex scenarios
  • wrk requires Lua scripting for advanced features, whereas drill provides built-in functionality for common testing needs
  • drill offers more detailed reporting and assertion capabilities out of the box
  • wrk is generally faster and more lightweight, suitable for pure performance benchmarking
18,056

HTTP load generator, ApacheBench (ab) replacement

Pros of hey

  • Written in Go, which may offer better performance for some use cases
  • Simpler command-line interface, easier to use for basic load testing
  • Supports HTTP/2 out of the box

Cons of hey

  • Less flexible than drill for complex scenarios
  • Lacks support for custom scripting or advanced request chaining
  • Limited reporting options compared to drill's detailed output

Code comparison

hey:

hey -n 1000 -c 100 https://example.com

drill:

---
concurrency: 4
base: 'http://example.com'
iterations: 10

plan:
  - name: Fetch users
    request:
      url: /api/users

Summary

hey is a straightforward load testing tool written in Go, offering simplicity and HTTP/2 support. drill, on the other hand, provides more flexibility with its YAML-based configuration and advanced scripting capabilities. hey is better suited for quick, simple load tests, while drill excels in complex scenarios requiring detailed control and reporting.

4,261

A constant throughput, correct latency recording variant of wrk

Pros of wrk2

  • More accurate latency measurements due to coordinated omission compensation
  • Better suited for high-throughput, constant-rate load testing
  • Includes built-in scripting support using Lua

Cons of wrk2

  • Less flexible in terms of request customization compared to drill
  • Limited to HTTP/HTTPS protocols
  • Steeper learning curve for users unfamiliar with Lua scripting

Code Comparison

wrk2:

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

drill:

plan:
  - name: Post data
    request:
      url: https://example.com/api
      method: POST
      body: foo=bar&baz=quux
      headers:
        Content-Type: application/x-www-form-urlencoded

Summary

wrk2 excels in accurate, high-throughput load testing with built-in scripting capabilities, while drill offers more flexibility in request customization and easier configuration through YAML files. wrk2 is better suited for performance-critical scenarios, whereas drill provides a more user-friendly approach for general-purpose API testing and benchmarking.

24,772

Write scalable load tests in plain Python 🚗💨

Pros of Locust

  • More mature and widely adopted project with a larger community
  • Supports distributed load testing across multiple machines
  • Provides a web-based UI for real-time monitoring and control

Cons of Locust

  • Requires Python knowledge to write test scenarios
  • Can be more resource-intensive for high-concurrency tests
  • Steeper learning curve for complex test scenarios

Code Comparison

Locust example:

from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 5)

    @task
    def index_page(self):
        self.client.get("/")

Drill example:

plan:
  - name: Fetch home page
    request:
      url: https://example.com/

Locust uses Python for defining test scenarios, while Drill uses YAML for a more declarative approach. Locust provides more flexibility and programmability, whereas Drill offers a simpler configuration for basic load testing needs.

Both tools serve the purpose of load testing, but Locust is better suited for complex, distributed scenarios, while Drill excels in simplicity and ease of use for straightforward load testing tasks.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Drill

Drill is a HTTP load testing application written in Rust. The main goal for this project is to build a really lightweight tool as alternative to other that require JVM and other stuff.

You can write benchmark files, in YAML format, describing all the stuff you want to test.

It was inspired by Ansible syntax because it is really easy to use and extend.

Here is an example for benchmark.yml:

---

concurrency: 4
base: 'http://localhost:9000'
iterations: 5
rampup: 2

plan:
  - name: Include comments
    include: comments.yml

  - name: Fetch users
    request:
      url: /api/users.json

  - name: Fetch organizations
    request:
      url: /api/organizations

  - name: Fetch account
    request:
      url: /api/account
    assign: foo

  - name: Fetch manager user
    request:
      url: /api/users/{{ foo.body.manager_id }}

  - name: Assert request response code
    assert:
      key: foo.status
      value: 200

  - name: Assign values
    assign:
      key: bar
      value: "2"

  - name: Assert values
    assert:
      key: bar
      value: "2"

  - name: Fetch user from assign
    request:
      url: /api/users/{{ bar }}

  - name: Fetch some users
    request:
      url: /api/users/{{ item }}
    with_items:
      - 70
      - 73
      - 75

  - name: Tagged user request
    request:
      url: /api/users/70
    tags:
      - tag_user

  - name: Fetch some users by hash
    request:
      url: /api/users/{{ item.id }}
    with_items:
      - { id: 70 }
      - { id: 73 }
      - { id: 75 }

  - name: Fetch some users by range, index {{ index }}
    request:
      url: /api/users/{{ item }}
    with_items_range:
      start: 70
      step: 5
      stop: 75

  - name: Fetch some users from CSV, index {{ index }}
    request:
      url: /api/users/contacts/{{ item.id }}
    with_items_from_csv: ./fixtures/users.csv
    shuffle: true

  - name: POST some crafted JSONs stored in CSV, index {{ index }}
    request:
      url: /api/transactions
      method: POST
      body: '{{ item.txn }}'
      headers:
        Content-Type: 'application/json'
    with_items_from_csv:
      file_name: ./fixtures/transactions.csv
      quote_char: "\'"

  - name: Fetch no relative url
    request:
      url: http://localhost:9000/api/users.json

  - name: Interpolate environment variables
    request:
      url: http://localhost:9000/api/{{ EDITOR }}

  - name: Support for POST method
    request:
      url: /api/users
      method: POST
      body: foo=bar&arg={{ bar }}

  - name: Login user
    request:
      url: /login?user=example&password=3x4mpl3

  - name: Fetch counter
    request:
      url: /counter
    assign: memory

  - name: Fetch counter
    request:
      url: /counter
    assign: memory

  - name: Fetch endpoint
    request:
      url: /?counter={{ memory.body.counter }}

  - name: Reset counter
    request:
      method: DELETE
      url: /

  - name: Exec external commands
    exec:
      command: "echo '{{ foo.body }}' | jq .phones[0] | tr -d '\"'"
    assign: baz

  - name: Custom headers
    request:
      url: /admin
      headers:
        Authorization: Basic aHR0cHdhdGNoOmY=
        X-Foo: Bar
        X-Bar: Bar {{ memory.headers.token }}

  - name: One request with a random item
    request:
      url: /api/users/{{ item }}
    with_items:
      - 70
      - 73
      - 75
    shuffle: true
    pick: 1

  - name: Three requests with random items from a range
    request:
      url: /api/users/{{ item }}
    with_items_range:
      start: 1
      stop: 1000
    shuffle: true
    pick: 3

As you can see, you can play with interpolations in different ways. This will let you specify a benchmark with different requests and dependencies between them.

If you want to know more about the benchmark file syntax, read this

Install

Right now, the easiest way to get drill is to go to the latest release page and download the binary file for your platform.

Another way to install drill, if you have Rust available in your system, is with cargo:

cargo install drill
drill --benchmark benchmark.yml --stats

or download the source code and compile it:

git clone git@github.com:fcsonline/drill.git && cd drill
cargo build --release
./target/release/drill --benchmark benchmark.yml --stats

Dependencies

OpenSSL is needed in order to compile Drill, whether it is through cargo install or when compiling from source with cargo build.

Depending on your platform, the name of the dependencies may differ.

Linux

Install libssl-dev and pkg-config packages with your favorite package manager (if libssl-dev is not found, try other names like openssl or openssl-devel).

macOS

First, install the Homebrew package manager.

And then install openssl with Homebrew.

Windows

First, install vcpkg.

And then run vcpkg install openssl:x64-windows-static-md.

Demo

demo

Features

This is the list of all features supported by the current version of drill:

  • Concurrency: run your benchmarks choosing the number of concurrent iterations.
  • Multi iterations: specify the number of iterations you want to run the benchmark.
  • Ramp-up: specify the amount of time, in seconds, that it will take drill to start all iterations.
  • Delay: introduce controlled delay between requests. Example: delay.yml
  • Dynamic urls: execute requests with dynamic interpolations in the url, like /api/users/{{ item }}
  • Dynamic headers: execute requests with dynamic headers. Example: headers.yml
  • Interpolate environment variables: set environment variables, like /api/users/{{ EDITOR }}
  • Executions: execute remote commands with test plan data.
  • Assertions: assert values during the test plan. Example: iterations.yml
  • Request dependencies: create dependencies between requests with assign and url interpolations.
  • Split files: organize your benchmarks in multiple files and include them.
  • CSV support: read CSV files and build N requests fill dynamic interpolations with CSV data.
  • HTTP methods: build request with different http methods like GET, POST, PUT, PATCH, HEAD or DELETE.
  • Cookie support: create benchmarks with sessions because cookies are propagates between requests.
  • Stats: get nice statistics about all the requests. Example: cookies.yml
  • Thresholds: compare the current benchmark performance against a stored one session and fail if a threshold is exceeded.
  • Tags: specify test plan items by tags.

Test it

Go to the example directory and you'll find a README how to test it in a safe environment.

Disclaimer: We really recommend not to run intensive benchmarks against production environments.

Command line interface

Full list of cli options, which is available under drill --help

drill 0.8.3
HTTP load testing application written in Rust inspired by Ansible syntax

USAGE:
    drill [FLAGS] [OPTIONS] --benchmark <benchmark>

FLAGS:
    -h, --help                      Prints help information
        --list-tags                 List all benchmark tags
        --list-tasks                List benchmark tasks (executes --tags/--skip-tags filter)
    -n, --nanosec                   Shows statistics in nanoseconds
        --no-check-certificate      Disables SSL certification check. (Not recommended)
    -q, --quiet                     Disables output
        --relaxed-interpolations    Do not panic if an interpolation is not present. (Not recommended)
    -s, --stats                     Shows request statistics
    -V, --version                   Prints version information
    -v, --verbose                   Toggle verbose output

OPTIONS:
    -b, --benchmark <benchmark>    Sets the benchmark file
    -c, --compare <compare>        Sets a compare file
    -r, --report <report>          Sets a report file
        --skip-tags <skip-tags>    Tags to exclude
        --tags <tags>              Tags to include
    -t, --threshold <threshold>    Sets a threshold value in ms amongst the compared file
    -o, --timeout <timeout>        Set timeout in seconds for all requests

Roadmap

  • Complete and improve the interpolation engine
  • Add writing to a file support

Donations

If you appreciate all the job done in this project, a small donation is always welcome:

"Buy Me A Coffee"

Contribute

This project started as a side project to learn Rust, so I'm sure that is full of mistakes and areas to be improve. If you think you can tweak the code to make it better, I'll really appreciate a pull request. ;)