Giter VIP home page Giter VIP logo

bender's Introduction

Bender

Bender makes it easy to build load testing applications for services using protocols like HTTP, Thrift, Protocol Buffers and many more. Bender provides a library of flexible, powerful primitives that can be combined (with plain Go code) to build load testers customized to any use case and that evolve with your service over time.

Bender provides two different approaches to load testing. The first, LoadTestThroughput, gives the tester control over the throughput (QPS), but not over the concurrency. This one is very well suited for services that are open to the Internet, like web services, and even backend Thrift or Protocol Buffer services, since it will just keep sending requests, even if the service is struggling. The second approach, LoadTestConcurrency, gives the tester control over the concurrency, but not over the throughput. This approach is better suited to testing services that require lots of concurrent connections, and need to be tested for resource limits.

That Bender is a library makes it flexible and easy to extend, but means it takes longer to create an initial load tester. As a result, we've focused on creating easy-to-follow tutorials that are written for people unfamiliar with Go, along with documentation for all the major functions in the library.

Getting Started

The easiest way to get started with Bender is to use one of the tutorials:

Documentation

The package documentation is available on godoc.org. The function and data structure documentation is also available there.

Performance

We have only informal, anecdotal evidence for the maximum performance of Bender. For example, in a very simple load test using a Thrift server that just echoes a message, Bender was able to send 7,000 QPS from a single EC2 m3.2xlarge host. At higher throughput the Bender "overage" counter increased, indicating that either the Go runtime, the OS or the host was struggling to keep up.

We have found a few things that make a big difference when running load tests. First, the Go runtime needs some tuning. In particular, the Go GC is very immature, so we prefer to disable it using the GOGC=off environment variable. In addition, we have seen some gains from setting GOMAXPROCS to twice the number of CPUs.

Secondly, the Linux TCP stack for a default server installation is usually not tuned to high throughput servers or load testers. After some experimentation, we have settled on adding these lines to /etc/sysctl.conf, after which you can run sysctl -p to load them (although it is recommended to restart your host at this point to make sure these take effect).

# /etc/sysctl.conf
# Increase system file descriptor limit
fs.file-max = 100000

# Increase ephermeral IP ports
net.ipv4.ip_local_port_range = 10000 65000

# Increase Linux autotuning TCP buffer limits
# Set max to 16MB for 1GE and 32M (33554432) or 54M (56623104) for 10GE
# Don't set tcp_mem itself! Let the kernel scale it based on RAM.
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.optmem_max = 40960
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# Make room for more TIME_WAIT sockets due to more clients,
# and allow them to be reused if we run out of sockets
# Also increase the max packet backlog
net.core.netdev_max_backlog = 50000
net.ipv4.tcp_max_syn_backlog = 30000
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10

# Disable TCP slow start on idle connections
net.ipv4.tcp_slow_start_after_idle = 0

This is a slightly modified version of advice taken from this source: http://www.nateware.com/linux-network-tuning-for-2013.html#.VBjahC5dVyE

In addition, it helps to increase the open file limit with something like:

ulimit -n 100000

What Is Missing

Bender does not provide any support for sending load from more than one machine. If you need to send more load than a single machine can handle, or you need the requests to come from multiple physical hosts (or different networks, or whatever), you currently have to write your own tools. In addition, the histogram implementation used by Bender is inefficient to send over the network, unlike q-digest or t-digest, which we hope to implement in the future.

Bender does not provide any visualization tools, and has a relatively simple set of measurements, including a customizable histogram of latencies, an error rate and some other summary statistics. Bender does provide a complete log of everything that happens during a load test, so you can use existing tools to graph any aspect of that data, but nothing in Bender makes that easy right now.

Bender currently provides helper functions for DHCPv6, DNS, HTTP, Thrift and TFTP. We appreciate Pull Requests for other protocols.

The load testers we have written internally with Bender have a lot of common command line arguments, but we haven't finalized a set to share as part of the library.

Comparison to Other Load Testers

JMeter

JMeter provides a GUI to configure and run load tests, and can also be configured via XML (really, really not recommended by hand!) and run from the command line. JMeter uses the same approach as LoadTestConcurrency in Bender, which is not a good approach to load testing services (see the Bender docs and the Iago philosophy for more details on why that is). It isn't easy to extend JMeter to handle new protocols, so it doesn't have support for Thrift or Protobuf. It is relatively easy to extend other parts of JMeter by writing Java code, however, and the GUI makes it easy to plug all the pieces together.

Iago

Iago is Twitter's load testing library and it is the inspiration for Bender's LoadTestThroughput function. Iago is a Scala library written on top of Netty and the Twitter Finagle libraries. As a result, Iago is powerful, but difficult to understand, extend and configure. It was frustration with making Iago work that led to the creation of Bender.

The Grinder

The Grinder has the same load testing approach as JMeter, but allows scripting via Jython, which makes it more flexible and extensible. The Grinder uses threads, which limits the concurrency at which it can work, and makes it hard to implement things like Bender's LoadTestThroughput function. The Grinder does have support for conveniently running distributed load tests.

Copyright

Copyright 2014-2018 Pinterest, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Attribution

Bender includes open source from the following sources:

bender's People

Contributors

andybons avatar cgordon avatar dbravender avatar dependabot[bot] avatar earlgreyz avatar ecoworld007 avatar fishy avatar hchaoshun avatar hugelgupf avatar johannespetzold avatar jparise avatar la0rg avatar lysu avatar pmazzini avatar triketora avatar vdobler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bender's Issues

not enough arguments in thrift/thrift.go

Hi.
I am experiencing some issues, while building your project.

~/bender/thrift$ go build
thrift.go:24:2: cannot find package "git.apache.org/thrift.git/lib/go/thrift" in any of:
/home/oceanfish81/gollvm_dist/src/git.apache.org/thrift.git/lib/go/thrift (from $GOROOT)
/home/oceanfish81/go/src/git.apache.org/thrift.git/lib/go/thrift (from $GOPATH)

~/bender/thrift$ go get -u git.apache.org/thrift.git/lib/go/thrift
$ go build

_/home/oceanfish81/bender/thrift

./thrift.go:35:25: error: not enough arguments
./thrift.go:55:38: error: not enough arguments
./thrift.go:60:16: error: argument 1 has incompatible type (missing method 'Deadline')
./thrift.go:60:10: error: not enough arguments

~/bender$ git pull
Already up to date.

I am using

$ go version
go version go1.15.2 gollvm LLVM 12.0.0git linux/amd64
.

Here is my environment:

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/oceanfish81/.cache/go-build"
GOENV="/home/oceanfish81/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/oceanfish81/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/oceanfish81/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/oceanfish81/gollvm_dist"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/oceanfish81/gollvm_dist/tools"
GCCGO="/home/oceanfish81/gollvm_dist/bin/llvm-goc"
AR="ar"
CC="/usr/bin/clang"
CXX="/usr/bin/clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build167274628=/tmp/go-build -gno-record-gcc-switches -funwind-tables"

gRPC Support

Hello. 👋 Looking to try using bender for gRPC services. Are there any plans to add executors for gRPC any time soon?

UniformIntervalGenerator implementation is Buggy

// UniformIntervalGenerator creates and IntervalGenerator that outputs 1/rate every time it is
// called. Boring, right?
func UniformIntervalGenerator(rate float64) IntervalGenerator {
	irate := int64(rate / float64(time.Second))
	return func(_ int64) int64 {
		return irate
	}
}

This implementation is buggy because if I pass in float64(time.Second) for rate, then irate = 1, and that value is passed into LoadTestThroughput as a Duration value, which means the wait time will be 1 nanosecond. If I pass in 1.0 with the intention of 1.0 QPS, then the resulting wait time will be 0 nanoseconds.

Looks like irate should be int64(float64(time.Second) / rate) instead of the other way around. The comments suggests that this should be the case.

Changing to the proposed fix will also help create a consistent API with ExponentialIntervalGenerator (i.e. passing in the QPS value).

This is a Golang playground that demonstrates my understanding. I substituted the math from the functions and used the same QPS rate for both.
https://play.golang.org/p/jKXTYHWSC2

I can make a pull request if this a legitimate bug.

Update the bender API to look more like jbender

The API for bender was created before the API for jbender (see https://github.com/pinterest/jbender). The API for jbender is more elegant and requires a LOT less memory allocations in the main loop (as it sends far fewer events). This would be a non-backwards compatible change, but given the way people vendor dependencies that should be alright for existing users.

Issues with running go install

Screen Shot 2021-06-02 at 2 54 21 AM

Also, when running " thrift --out src/hellothrift --gen go:package_prefix=src/hellothrift src/hellothrift/hello.thrift" , i do not get the exact 3 files in the hello directory.

Screen Shot 2021-06-02 at 2 55 05 AM

Any ideas?

golint reporting errors

golint ./...
bender.go:25:6: exported type IntervalGenerator should have comment or be unexported
bender.go:27:6: exported type RequestExecutor should have comment or be unexported
bender_test.go:27:56: don't use underscores in Go names; func parameter expected_msgs should be expectedMsgs
bender_test.go:29:3: don't use underscores in Go names; var actual_msg should be actualMsg
recorders.go:25:6: exported type Recorder should have comment or be unexported
recorders.go:27:1: exported function Record should have comment or be unexported
recorders.go:39:1: exported function NewLoggingRecorder should have comment or be unexported
recorders.go:45:1: exported function NewHistogramRecorder should have comment or be unexported
hist/hist.go:26:6: exported type Histogram should have comment or be unexported
hist/hist.go:37:1: exported function NewHistogram should have comment or be unexported
hist/hist.go:41:1: exported method Histogram.Start should have comment or be unexported
hist/hist.go:45:1: exported method Histogram.End should have comment or be unexported
hist/hist.go:49:1: exported method Histogram.Add should have comment or be unexported
hist/hist.go:62:1: exported method Histogram.AddError should have comment or be unexported
hist/hist.go:64:2: should replace h.errCnt += 1 with h.errCnt++
hist/hist.go:67:1: exported method Histogram.Percentiles should have comment or be unexported
hist/hist.go:76:2: don't use underscores in Go names; var p_idx should be pIdx
hist/hist.go:93:1: exported method Histogram.Average should have comment or be unexported
hist/hist.go:97:1: exported method Histogram.ErrorPercent should have comment or be unexported
http/http.go:26:6: exported type HttpBodyValidator should have comment or be unexported
http/http.go:26:6: type HttpBodyValidator should be HTTPBodyValidator
http/http.go:26:6: type name will be used as http.HttpBodyValidator by other packages, and that stutters; consider calling this BodyValidator
http/http.go:28:1: exported function CreateHttpExecutor should have comment or be unexported
http/http.go:28:6: func CreateHttpExecutor should be CreateHTTPExecutor
thrift/thrift.go:28:6: exported type ThriftClientExecutor should have comment or be unexported
thrift/thrift.go:28:6: type name will be used as thrift.ThriftClientExecutor by other packages, and that stutters; consider calling this ClientExecutor
thrift/thrift.go:30:1: exported function NewThriftRequestExec should have comment or be unexported
thrift/thrift.go:49:1: exported function DeserializeThriftMessage should have comment or be unexported
thrift/thrift.go:52:8: var typeId should be typeID
thrift/thrift.go:52:16: var seqId should be seqID

how to use thrift support High concurrency?

I use thrift for go language to test High concurrency,but only support less than 1000 goroutines ,when bigger,it will report "getsockopt: connection timed out",how i can do to resolve it ? i found go thrift only support TSimpleServer,but other language support TSimpleServer,TThreadedServer,TThreadPoolServer,TNonBlockingServer

Revisit the performance notes in the README

The bender library came out before most of the major improvements to the Go GC algorithms, and it is likely to perform a lot better with those improvements. It would be great to go back and revisit those numbers with a more modern Go implementation.

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.