Giter VIP home page Giter VIP logo

wrecker's Introduction

Hackage Travis CI Status

wrecker

wrecker is an HTTP benchmarking library and executable for profiling several API actions.

Why?

There are plenty of HTTP profilers in existence: wrk, ab, JMeter, LoadRunner, etc. Most profilers provide some facility for scripting and using the responses of the previous requests for future requests. However, the scripting facility is usually weak and esoteric.

wrecker is designed from the ground-up for scripting complex API sequences sublimely. Benchmarks can utilize a wreq-like interface, perhaps the easiest-to-use Haskell library for HTTP interaction, and quickly create wonderful, typed API clients.

How does it compare to my current http profiling?

If you are happy with your HTTP profiling setup, then wrecker doesn't offer a reason to switch ... it does have an interactive mode.

Wrecker Interactive Command Line

That makes it a little easier to know when to stop.

Quick Start

wrecker provides a simple executable wreck which takes a single URL to profile.

$ wreck http://localhost:3000/root

wreck terminal output

The wreck executable is not that interesting. wrecker is more interesting when used as a library to create a suite of benchmarks.

Similar functionality to wreck can be executed from ghci:

$ ghci
> import Wrecker
> import Network.Wreq.Wrecker
> runOne defaultOptions $ withWreq $ \sess -> get sess "http://localhost:3000/root"

Running with ghci is okay to get a feel for wrecker, but it is recommended that all benchmarks are compiled with optimizations, the threaded library, and run with the RTS options -N -I0 -qg.

Accuracy

wreck produces results that are close to wrk and ab when the number of connections are below 100. As the number of connections increases to 1,000 and 10,000 wrk continues to work well, but wrecker and ab produce inflated numbers.

You can play around with comparing wreck to wrk and ab in the VM created from the provided Vagrant file.

vagrant up && vagrant ssh
cd /vagrant && cabal run example-server -- 10000

The 100000 is the threadDelay for the requests in microseconds.

Example Results
  • 100 Connections
    • wrk -d 10 -t 2 -c 100 http://localhost:3000/root
      • mean: 104.78 ms
      • variance: 0.009 ms
    • ab -t 10 -c 100 http://localhost:3000/root
      • mean: 106.9 ms
      • variance: 0.05 ms
    • wreck --concurrency=100 --run-timed=10 http://localhost:3000/root
      • mean: 105.6 ms
      • variance: 000.17 ms
  • 1000 Connections
    • wrk -d 10 -t 2 -c 100 http://localhost:3000/root
      • mean: 135.42 ms
      • variance: 0.009 ms
    • ab -t 10 -c 100 http://localhost:3000/root
      • mean: 218.61 ms
      • variance: 235.2 ms
    • wreck --concurrency=100 --run-timed=10 http://localhost:3000/root
      • mean: 316.0 ms
      • variance: 000.90 ms

A More Complicated Benchmark

In addition to benchmarking a single URL, the wrecker library can create a suite of benchmarks, each of which can contain multiple endpoints to profile.

The example below uses the wrecker's wreq interface but any http-client based library could be used.

import Wrecker
import Network.Wreq.Wrecker

main = defaultMain
  [ ( "first page"
    , withWreq $ \sess do
        get sess "http://localhost:3000/page1/page1.css"
        get sess "http://localhost:3000/page1/page1.js"
    )
  , ( "second page"
    , withWreq $ \sess do
        get sess "http://localhost:3000/page2/page2.css"
        get sess "http://localhost:3000/page2/page2.js"
    )
  ]

Examples

wrecker is particularly useful for benchmarking a series of dependent requests. wrecker includes a more complex typed API client example. The tutorial is below, but you can run the examples with the following commands.

  • Run the client and server example with cabal run example
  • Run the client with cabal run example-client
  • Run the serve with cabal run example-server

Create a Typed API Client with wrecker

Here is what a typed API client looks like.

Example Script

testScript :: Int -> Environment -> IO ()
testScript port = withWreq $ \sess -> do
  Root { products
       , login
       , checkout
       }             <- get sess (rootRef port)
  firstProduct : _   <- get sess products
  userRef            <- rpc sess login
                                  ( Credentials
                                    { userName = "[email protected]"
                                    , password = "password"
                                    }
                                  )
  User { usersCart } <- get sess userRef
  Cart { items }     <- get sess usersCart

  insert sess items firstProduct
  rpc sess checkout cart

Output

Output from running

cabal build example -- --concurrency=1000 --interactive

Example terminal output

Full Tutorial

Click here to see the full type API tutorial

Memory Use

wrecker calculates statistics incrementally and is able to use a constant amount of memory regardless of the length of time it is run.

Here is a heap snapshot for a thousand concurrent connections

Heap Snapshot

wrecker's People

Contributors

jfischoff avatar lorenzo avatar michaelxavier avatar

Stargazers

Peter Výboch avatar Alex Vzorov avatar  avatar  avatar Chris Stryczynski avatar Dee Cheung avatar Daniel Kahlenberg avatar YAMAMOTO Yuji avatar Akihito Koriyama avatar Joshua Gorospe avatar Marco Z avatar  avatar Alexander Biehl avatar

Watchers

 avatar  avatar YAMAMOTO Yuji avatar James Cloos avatar  avatar  avatar

Forkers

soostone purefn

wrecker's Issues

Upgrade to GHC 8.8.3

I'm trying to plug wrecker as a part of my benchmarks suite in the project. As the project uses a newer GHC, I can't compile wrecker under the same project

My API is Servant so I could just reuse all existing API types with wrecker if it was compatible with the newer GHCs.

What's the path for upgrading wrecker to a new GHC, say lts-15.5 / GHC 8.8.3?

Example does not seem to work

/home/chris/Projects/Haskell/wrecker/app/Main.hs:14:7: error:
    • Couldn't match type ‘Response
                             bytestring-0.10.8.2:Data.ByteString.Lazy.Internal.ByteString’
                     with ‘()’
      Expected type: Environment -> IO ()
        Actual type: Environment
                     -> IO
                          (Response
                             bytestring-0.10.8.2:Data.ByteString.Lazy.Internal.ByteString)
    • In the expression:
        withWreq $ \ sess -> do get sess "https://trycatchchris.co.uk"
      In the expression:
        ("first page", 
         withWreq $ \ sess -> do get sess "https://trycatchchris.co.uk")
      In the first argument of ‘defaultMain’, namely
        ‘[("first page", withWreq $ \ sess -> do ...)]’
   |
14 |     , withWreq $ \sess -> do
   |       ^^^^^^^^^^^^^^^^^^^^^^...

app/Main.hs

import Control.Exception
import Control.Monad (void)
import Data.Monoid
import Network.HTTP.Client
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Options.Applicative
import Wrecker
import Wrecker.Options
import Network.Wreq.Wrecker

main :: IO ()
main = defaultMain
  [ ( "first page"
    , withWreq $ \sess -> do
        get sess "https://trycatchchris.co.uk"
    )
  ]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.