---
id: options
title: Options Reference
---

The `ghz` command line has numerous command line options.  You can run `ghz --help` to view all available options.

<AUTOGENERATED_TABLE_OF_CONTENTS>

### `--config`

Path to the JSON or TOML [config file](example_config.md) that specifies all the test settings.

Config file settings can be combined with command line arguments. CLI options overwrite config file options.

```sh
ghz --config=./config.json -c 20 -n 1000
```

### `--proto`

The path to The Protocol Buffer .proto file for input. If no `-proto` or `-protoset` options are used, we attempt to perform [server reflection](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md).

### `--protoset`

Alternatively we use compiled protoset file (containing compiled descriptors, produced by `protoc`) as input.
To create a protoset file, invoke `protoc` with the `*.proto` files that define the service. For example:

```sh
protoc --proto_path=. --descriptor_set_out=bundle.protoset *.proto
```

If no `-proto` or `-protoset` options are used, we attempt to perform server reflection.

### `--call`

A fully-qualified method name in 'package.Service/Method' or 'package.Service.Method' format. For example: `helloworld.Greeter.SayHello`. With regard to measurement, we use [WithStatsHandler](https://godoc.org/google.golang.org/grpc#WithStatsHandler) option to capture call metrics. Specifically we only capture the [End](https://godoc.org/google.golang.org/grpc/stats#End) event which contains stats when an RPC ends. This should include the download of the payload and deserializing of the data.

### `-i`, `--import-paths`

Comma separated list of proto import paths. The current working directory and the directory of the protocol buffer file specified using `-proto` are automatically added to the import list.

### `--cacert`

Path to the file containing trusted root certificates for verifying the server. By default `ghz` tries to create a secure connection using the system's default root certificate. The certificate file can be specified using `-cacert` option. The TLS verification can be skipped using `-skipTLS` option.

### `--cert`

Path to the file containing client certificate (public key), to present to the server. Must also provide `-key` option when this is used.

### `--key`

File containing client private key, to present to the server. Must also provide `-cert` option.

### `--cname`

Server name override when validating TLS certificate.

### `--skipTLS`

Skip TLS client verification of the server's certificate chain and host name.

### `--insecure`

Use plaintext and insecure connection.

### `--authority`

Value to be used as the `:authority` pseudo-header. Only works if `-insecure` is used.

### `--async`

Make requests asynchronous as soon as possible. Does not wait for request to finish before sending next one.

### `-r`, `--rps`

Rate limit in how many requsts per second (RPS) we perform in total. Default is no rate limit. The total RPS will be distributed among all the workers as specified by concurrency options.

### `--load-schedule`

Specifies the load schedule. Options are `const`, `step`, or `line`. Default is `const`.  
With `const` load schedule we attempt to perform a constant RPS load as specified with the `q` option.  
With `step` load schedule we do a step increase or decrease of RPS load as dictated by step load options: `load-start`, `load-step`, `load-end`, `load-step-duration`, and `load-max-duration`.
With `line` load schedule we do a linear increase or decrease of RPS load as dictated by step load options: `load-start`, `load-step`, `load-end`, and `load-max-duration`. Linear load is essentially step load with slop being specified using `load-step` option and `load-step-duration` is `1s`.

Examples:

```sh
-n 10000 -c 10 --load-schedule=step --load-start=50 --load-step=10 --load-step-duration=5s
```

Performs step load starting at `50` RPS and increasing by `10` RPS every `5s` until we reach `10000` total requests. The RPS load is distributed among the `10` workers, all sharing `1` connection.

```sh
-n 10000 -c 10 --load-schedule=step --load-start=50 --load-end=150 --load-step=10 --load-step-duration=5s
```

Performs step load starting at `50` RPS and increasing by `10` RPS every `5s` until we reach `150` RPS at which point the load is sustained at constant RPS rate until we reach `10000` total requests. The RPS load is distributed among the `10` workers, all sharing `1` connection.

```sh
-n 10000 -c 10 --load-schedule=step --load-start=50 --load-step=10 --load-step-duration=5s --load-max-duration=60s
```

Performs step load starting at `50` RPS and increasing by `10` RPS every `5s` until `60s` has elapsed at which point the load is sustained at that RPS rate until we reach `10000` total requests. The RPS load is distributed among the `10` workers, all sharing `1` connection.

```sh
-n 10000 -c 10 --load-schedule=line --load-start=200 --load-step=-2 --load-end=50
```

Performs linear load starting at `200` RPS and decreasing by `2` RPS every `1s` until `20` RPS has been reached, at which point the load is sustained at that RPS rate until we reach `10000` total requests. The RPS load is distributed among the `10` workers, all sharing `1` connection.

### `--load-start`

Specifies the starting RPS load value for step or line load schedules.

### `--load-step`

Specifies the load step value or slope value for step or line schedules.

### `--load-end`

Optional, specifies the load end value for step or line load schedules. Load adjustment is performed until either `load-end` rate is reached or `load-max-duration` duration has elapsed, which ever comes first.

### `--load-max-duration`

Optional, maximum duration to apply load adjustment. After this time has elapsed, constant load is performed at `load-end` setting value. Load adjustment is performed until either `load-end` rate is reached or `load-max-duration` duration has elapsed, which ever comes first.

### `-c`, `--concurrency`

Number of workers to run concurrently when using `const` concurrency scheduler.

### `--concurrency-schedule`

Controls the concurrency (number of workers) adjustment, similarly how `load` settings control the RPS load adjustment. Options are `const`, `step`, or `line`. Default is `const`.  

Examples:

```sh
-n 100000 --rps 200 --concurrency-schedule=step --concurrency-start=5 --concurrency-step=5 --concurrency-end=50 --concurrency-step-duration=5s
```

Performs RPS load of `200` RPS. The number of concurrent workers starts at `5` and is increased by `5` every `5s` until we reach `50` workers. At that point we keep the sustained `200` RPS load spread over the `50` workers until total of `10000` requests is reached. That means as we increase the number of total concurrent workers, their share of RPS load decreases.

```sh
-n 20000 -rps 200 --concurrency-schedule=step --concurrency-start=10 --concurrency-step=10 --concurrency-step-duration=5s --concurrency-max-duration=60s
```

Performs RPS load of `200` RPS. The number of concurrent workers starts at `10` and is increased by `10` every `5s` until `60s` has elapsed. At that point we keep the sustained `200` RPS load spread over the same number of workers until total of `20000` requests is reached.

```sh
-n 10000 --rps 200 --concurrency-schedule=line --concurrency-start=200 --concurrency-step=-2 --concurrency-end=20
```

Performs RPS load of `200` RPS. The number of concurrent workers starts at `200` and is decreased linearly by `2` every `1s` until we are at `20` concurrent workers. At that point we keep the sustained `200` RPS load spread over the same number of workers until total of `10000` requests is reached. As total number of active concurrent workers decreases, their share of RPS load increases.

### `--concurrency-start`

Concurrency start value for step and line concurrency schedules.

### `--concurrency-end`      

Concurrency end value for step and line concurrency schedules.

### `--concurrency-step=1`     

Concurrency step / slope value for step and line concurrency schedules.

### `--concurrency-step-duration`

Specifies the concurrency step duration value for step concurrency schedule.

### `--concurrency-max-duration`

Specifies the max concurrency adjustment duration value for step or line concurrency schedule.

### `-n`, `--total`

The total number of requests to run. Default is `200`. The combination of `-c` and `-n` are critical in how the benchmarking is done. `ghz` takes the `-c` argument and spawns that many worker goroutines. In parallel these goroutines each do their share (`n / c`) requests. So for example with the default `-c 50 -n 200` options we would spawn `50` goroutines which in parallel each do `4` requests.

### `-t`, `--timeout`

Timeout for each request. Default is `20s`, use zero value for infinite.

### `-z`, `--duration`

Duration of application to send requests. When duration is reached, application stops and exits. If duration is specified, `n` is ignored. Examples: `-z 10s` or `-z 3m`.

### `-x`, `--max-duration`

Maximum duration of application to send requests with `n` setting respected. If duration is reached before `n` requests are completed, application stops and exits. Examples: `-x 10s` or `-x 3m`.

### `--duration-stop`

Option on how to handle in-flight requests when duration specified using `duration` option is reached. Options are `close`, `wait`, and `ignore`. `close` will cause the connections to close immediately, and any requests that have yet to complete will likely error out and be reported with `transport is closing` error. `wait` will make all in-flight requests to be completed and reported. These requests still have the regular request `timeout` constraint. Finally, `ignore` option is similar to `close` that the connections are terminated immediately, however any in-flight requests that complete are completely ignored in the reporting.

### `-d`, `--data`

The call data as stringified JSON. If the value is `@` then the request contents are read from standard input (stdin). Example: `-d '{"name":"Bob"}'`.

For unary requests we accept a single message or an array of messages. In case of a single message we repeat the unary call with this message throughout the test. In case of array the messages will be sent in round-robin fashion. For example with `-d '[{"name":"Joe"},{"name":"Kate"},{"name":"Sara"}]'` the server will get Joe, Kate and Sara requests repeatedly.

For client streaming or bi-directional calls we accept a JSON array of messages, each element representing a single message within the stream call. For example: `-d '[{"name":"Joe"},{"name":"Kate"},{"name":"Sara"}]'` can be used as input for a client streaming or bidi call. In case of streaming calls if a single object is given for data then it is automatically converted to an array with single element. For example `-d '{"name":"Joe"}'` is equivalent to `-d '[{"name":"Joe"}]`. Round-robin for streaming requests is not supported.

In case of client streaming we send all the messages in the input array and then we close and receive.

### `-D`, `--data-file`

The path for call data JSON file. For example, `-D /home/user/file.json` or `-D ./file.json`.

### `-b`, `--binary`

The call data comes as serialized protocol buffer messages read from standard input. 

We support two formats of binary data: single message and multiple count-delimited messages. See [writing a message](https://developers.google.com/protocol-buffers/docs/gotutorial#writing_a_message) on how to serialize a single message. 

For multiple messages prefix each message with its length in bytes. See [streaming multiple messages](https://developers.google.com/protocol-buffers/docs/techniques#streaming) in protobuf documentation.

Code example:
```go
msg1 := &helloworld.HelloRequest{}
msg1.Name = "Alice"
msg2 := &helloworld.HelloRequest{}
msg2.Name = "Bob"

buf := proto.Buffer{}
_ = buf.EncodeMessage(msg1)
_ = buf.EncodeMessage(msg2)
			
binData := buf.Bytes() // pass this as input
```

### `-B`, `--binary-file`

Path for the call data as serialized binary message. The format is the same as for `-b` switch.

### `-m`, `--metadata`

Request metadata as stringified JSON.

### `-M`, `--metadata-file`

Path for call metadata JSON file. For example, `-M /home/user/metadata.json` or `-M ./metadata.json`.

### `--stream-interval`

Stream interval duration. Spread stream sends by given amount. Only applies to client and bidi streaming calls. Example: `100ms`.

### `--stream-call-duration`

Maximum stream call duration. For client streaming and bidi calls, we'll send messages until this duration expires.

For server streaming calls we will receive message until the duration has expired. Note that in server streaming calls the cancellation will result in call cancelled error.  

Example: `500ms`.

### `--stream-call-count`

The maximum number of message sends or receives the client will perform in a streaming call before closing the stream and ending the call. For client and bidi streaming calls this dictates the number of messages we will send.

If the data array contains more elements than the count, only data up to the number specified will be used.

If the data array contains fewer elements than the count specified, all the data will be iterated over repeatedly until count limit is reached. 

For server streaming calls we will receive message until the specified count is reached. Note that in server streaming calls the cancellation will result in call cancelled error.  

Examples:

```sh
--stream-call-count=2 -d '[{"name":"Joe"},{"name":"Kate"},{"name":"Sara"}]'
```

Will cause only `[{"name":"Joe"},{"name":"Kate"}]` to be sent. Similarly:

```sh
--stream-call-count=5 -d '[{"name":"Joe"},{"name":"Kate"},{"name":"Sara"}]'
```

Will cause `[{"name":"Joe"},{"name":"Kate"},{"name":"Sara"},{"name":"Joe"},{"name":"Kate"}]` to be sent.

### `--stream-dynamic-messages`

In streaming calls, regenerate and apply call template data on every message send operation.
This is helpful in combination with template functionality to generate data _for every message sent_ in a streaming call.
For example:

```sh
--stream-dynamic-messages=true --stream-call-count=5 -d '{"name":"{{randomString 8 }}"}'
```

Will result in streaming call with the following data sent:

```json
[{"name":"sKNdMCIb"},{"name":"KLVXDvn1"},{"name":"RJ3knnBh"},{"name":"FTBqQ7nl"},{"name":"FzeMQIWo"}]
```

Contrast that with the default dynamic messages setting turned off; which means the template data will be applied only once for each stream call request, but _not_ for each message sent _in_ the streaming call.

```sh
--stream-call-count=5 -d '{"name":"{{randomString 8 }}"}'
```

Results in the following data sent:

```json
[{"name":"5hL64dd0"},{"name":"5hL64dd0"},{"name":"5hL64dd0"},{"name":"5hL64dd0"},{"name":"5hL64dd0"}]
```

### `--reflect-metadata`

Reflect metadata as stringified JSON used only for reflection request.

### `--max-recv-message-size`

Maximum message size the client can receive. Can be specified as bytes, or using [human readable value](https://pkg.go.dev/github.com/dustin/go-humanize#ParseBytes) such as `42 MB`.

### `--max-send-message-size`

Maximum message size the client can send. Can be specified as bytes, or using [human readable value](https://pkg.go.dev/github.com/dustin/go-humanize#ParseBytes) such as `42 MB`.

### `-o`, `--output`

Output path. If none is provided by default we print to standard output (stdout).

### `-O`, `--format`

Output type. If none provided, a summary is printed.

- `"csv"` - outputs the response metrics in comma-separated values format.
- `"json"` - outputs the metrics report in JSON format.
- `"pretty"` - outputs the metrics report in pretty JSON format.
- `"html"` - outputs the metrics report as HTML.
- `"influx-summary"` - outputs the metrics summary as InfluxDB line protocol.
- `"influx-details"` - outputs the metrics details as InfluxDB line protocol.
- `"prometheus"` - outputs the metrics summary in Prometheus exposition format.

See [output formats page](output.md) for details.


### `--skipFirst`

Skip the first `n` responses from the report. Helps remove initial warm-up requests from skewing the results.


### `--connections`

By default we use a single gRPC connection for the whole test run, and the concurrency (`-c`) is achieved using goroutine workers sharing this single connection. The number of gRPC connections used can be controlled using this parameter. This parameter cannot exceed concurrency option. The specified number of connections will be distributed evenly to be shared among the concurrency goroutine workers. So for example a concurrency of `10` and using `5` connections will result in `10` goroutine workers, each pair of `2` workers sharing `1` of the `5` connections. Each worker will get its share of the total number of requests specified using `-n` option.

### `--connect-timeout`

Connection timeout duration for the initial connection dial. Default is `10s`.

### `--keepalive`

Keepalive time duration. Only used if present and above `0`.

### `--name`

A user specified name for the test.

### `--tags`

JSON string representation of user-defined string tags. This is mainly for reporting purposes. For example `-tags '{"env":"staging","created by":"Joe Developer"}'`.

### `--cpus`

Number of used cpu cores to be used for the test. The default is the total number of logical CPUs on the local machine.

### `--debug`

Enables debug logging to a file specified by the path. The debug logger outputs JSON line format. Use this only for debugging purposes.

```sh
ghz --insecure \
  --proto ./protos/greeter.proto \
  --call helloworld.Greeter.SayHello \
  -d '{"name":"Joe"}' -c 5 -n 50 -m '{"request-id":"{{.RequestNumber}}", "timestamp":"{{.TimestampUnix}}"}' \
  --debug ./logs/debug.json \
  0.0.0.0:50051
```

### `-e`, `--enable-compression`               

Enable gzip compression on requests.

### `--lb-strategy`

Client load balancing strategy. For example: `--lb-strategy "round_robin"`

### `--count-errors`

By default stats for fastest, slowest, average, histogram, and latency distributions only take into account the responses with OK status. This option enabled counting of erroneous (non-OK) responses in stats calculations as well.

### `--disable-template-functions`

Disable execution of template functions within call data and metadata. This can be useful for some performance improvements. Note that if template functions are used within data with this option set to `true`, it will result in an error. If `--disable-template-data` is set to `true` this is automatically also set to `true`.

### `--disable-template-data`

Disable execution of templates within call data and metadata. This can be useful for some performance improvements. This automatically also sets `disable-template-functions` to `true`.

### `-v`, `--version`

Print the version.

### `-h`, `--help`                

Show context-sensitive help (also try --help-long and --help-man).

