Skip to content

emqx/emqtt-bench

Folders and files

NameName
Last commit message
Last commit date

Latest commit

91f0446 · Apr 22, 2025
Apr 2, 2025
Oct 13, 2021
Oct 10, 2024
Apr 3, 2025
Mar 9, 2023
Jul 20, 2022
Oct 10, 2024
Feb 7, 2025
Jun 11, 2024
Jul 12, 2019
Nov 18, 2024
Apr 22, 2025
Nov 21, 2024
Jan 20, 2025
Oct 18, 2024
Apr 3, 2025
Apr 3, 2025

Repository files navigation

Lightweight MQTT Benchmark Tool written in Erlang

image

eMQTT-Bench is a lightweight MQTT v5.0 benchmark tool written in Erlang.

You can download pre-built binary packeges from https://github.com/emqx/emqtt-bench/releases.

Build from source code

NOTE: Requires Erlang/OTP 22.3+ to build.

Install dependencies

emqtt-bench requires libatomic

# centos 7
sudo yum install libatomic
# ubuntu 20.04
sudo apt install libatomic1

make

git clone https://github.com/emqx/emqtt-bench.git
cd emqtt-bench
make

Optional, you could disable QUIC support if you have problem with compiling

BUILD_WITHOUT_QUIC=1 make

Connect Benchmark

Usage: emqtt_bench conn [--help <help>] [-d <dist>] [-h [<host>]] [-p [<port>]] [-V [<version>]] [-c [<count>]]
                        [-R [<conn_rate>]] [-i [<interval>]] [--ifaddr <ifaddr>] [--prefix <prefix>] [--shortids]
                        [-n [<startnumber>]] [--num-retry-connect [<num_retry_connect>]] [-R [<conn_rate>]]
                        [--reconnect [<reconnect>]] [-S [<ssl>]] [--ssl-version <sslversion>] [--cacertfile <cacertfile>]
                        [--certfile <certfile>] [--keyfile <keyfile>] [--ciphers <ciphers>]
                        [--signature-algs <signature_algs>] [--keyex-algs <keyex_algs>] [--quic [<quic>]] [--ws [<ws>]]
                        [--load-qst <nst_dets_file>] [-u <username>] [-P <password>] [-k [<keepalive>]] [-C [<clean>]]
                        [-x [<expiry>]] [-l <lowmem>] [--force-major-gc-interval [<force_major_gc_interval>]] [-Q [<qoe>]]
                        [--qoelog [<qoelog>]] [--prometheus] [--restapi [<restapi>]] [--log_to [<log_to>]]

  --help                     help information
  -d, --dist                 enable distribution port
  -h, --host                 mqtt server hostname or comma-separated hostnames [default: localhost]
  -p, --port                 mqtt server port number [default: 1883]
  -V, --version              mqtt protocol version: 3 | 4 | 5 [default: 5]
  -c, --count                max count of clients [default: 200]
  -R, --connrate             connection rate(/s), default: 0, fallback to use --interval [default: 0]
  -i, --interval             interval of connecting to the broker [default: 10]
  --ifaddr                   local ipaddress or interface address
  --prefix                   Client ID prefix. If not provided '$HOST_bench_(pub|sub)_$RANDOM_$N' is used, where $HOST is 
                             either the host name or the IP address provided in the --ifaddr option, $RANDOM is a random 
                             number and $N is the sequence number assigned for each client. If provided, the $RANDOM suffix 
                             will not be added.
  --shortids                 Use short client ID. If --prefix is provided, the prefix is added otherwise client ID is the 
                             assigned sequence number. [default: false]
  -n, --startnumber          The start point when assigning sequence numbers to clients. This is useful when running 
                             multiple emqtt-bench instances to test the same broker (cluster), so the start number can be 
                             planned to avoid client ID collision [default: 0]
  --num-retry-connect        number of times to retry estabilishing a connection before giving up [default: 0]
  --reconnect                max retries of reconnects. 0: disabled [default: 0]
  -S, --ssl                  ssl socket for connecting to server [default: false]
  --ssl-version              enforce tls version and implies ssl is enabled, 'tlsv1.1' | 'tlsv1.2' | 'tlsv1.3' | 
                             'tlsv1.3_nocompat'
  --cacertfile               CA certificate for server verification
  --certfile                 client certificate for authentication, if required by server
  --keyfile                  client private key for authentication, if required by server
  --ciphers                  Cipher suite for ssl/tls connection, comma separated list. e.g. 
                             TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
  --signature-algs           Signature algorithm for tlsv1.3 connection only, comma separated list. e.g. 
                             ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256
  --keyex-algs               Key exchange algorithm for tlsv1.3 connection only, comma separated list. e.g. 
                             secp384r1,secp256r1
  --quic                     QUIC transport [default: false]
  --ws                       websocket transport [default: false]
  --load-qst                 load quic session tickets from dets file
  -u, --username             username for connecting to server
  -P, --password             password for connecting to server
  -k, --keepalive            keep alive in seconds [default: 300]
  -C, --clean                clean session [default: true]
  -x, --session-expiry       Set 'Session-Expiry' for persistent sessions (seconds) [default: 0]
  -l, --lowmem               enable low mem mode, but use more CPU
  --force-major-gc-interval  interval in milliseconds in which a major GC will be forced on the bench processes.  a value of 
                             0 means disabled (default).  this only takes effect when used together with --lowmem. [default: 
                             0]
  -Q, --qoe                  set 'true' to enable QoE tracking. set 'dump' to dump QoE disklog to csv then exit [default: 
                             false]
  --qoelog                   Write QoE event logs to the QoE disklog file for post processing [default: ]
  --prometheus               Enable metrics collection via Prometheus. Usually used with --restapi to enable scraping 
                             endpoint.
  --restapi                  Enable REST API for monitoring and control. For now only serves /metrics. Can be set to IP:Port 
                             to listen on a specific IP and Port, or just Port to listen on all interfaces on that port. 
                             [default: disabled]
  --log_to                   Control where the log output goes. console: directly to the console      null: quietly, don't 
                             output any logs. [default: console]

For example, create 50K concurrent connections at the arrival rate of 100/sec:

./emqtt_bench conn -c 50000 -i 10

Sub Benchmark

Usage: emqtt_bench sub [--help <help>] [-d <dist>] [-h [<host>]] [-p [<port>]] [-V [<version>]] [-c [<count>]]
                       [-R [<conn_rate>]] [-i [<interval>]] [--ifaddr <ifaddr>] [--prefix <prefix>] [--shortids]
                       [-n [<startnumber>]] [--num-retry-connect [<num_retry_connect>]] [-R [<conn_rate>]]
                       [--reconnect [<reconnect>]] [-S [<ssl>]] [--ssl-version <sslversion>] [--cacertfile <cacertfile>]
                       [--certfile <certfile>] [--keyfile <keyfile>] [--ciphers <ciphers>]
                       [--signature-algs <signature_algs>] [--keyex-algs <keyex_algs>] [--quic [<quic>]] [--ws [<ws>]]
                       [--load-qst <nst_dets_file>] [-u <username>] [-P <password>] [-k [<keepalive>]] [-C [<clean>]]
                       [-x [<expiry>]] [-l <lowmem>] [--force-major-gc-interval [<force_major_gc_interval>]] [-Q [<qoe>]]
                       [--qoelog [<qoelog>]] [--prometheus] [--restapi [<restapi>]] [--log_to [<log_to>]] [-t <topic>]
                       [--payload-hdrs [<payload_hdrs>]] [-q [<qos>]]

  --help                     help information
  -d, --dist                 enable distribution port
  -h, --host                 mqtt server hostname or comma-separated hostnames [default: localhost]
  -p, --port                 mqtt server port number [default: 1883]
  -V, --version              mqtt protocol version: 3 | 4 | 5 [default: 5]
  -c, --count                max count of clients [default: 200]
  -R, --connrate             connection rate(/s), default: 0, fallback to use --interval [default: 0]
  -i, --interval             interval of connecting to the broker [default: 10]
  --ifaddr                   local ipaddress or interface address
  --prefix                   Client ID prefix. If not provided '$HOST_bench_(pub|sub)_$RANDOM_$N' is used, where $HOST is 
                             either the host name or the IP address provided in the --ifaddr option, $RANDOM is a random 
                             number and $N is the sequence number assigned for each client. If provided, the $RANDOM suffix 
                             will not be added.
  --shortids                 Use short client ID. If --prefix is provided, the prefix is added otherwise client ID is the 
                             assigned sequence number. [default: false]
  -n, --startnumber          The start point when assigning sequence numbers to clients. This is useful when running 
                             multiple emqtt-bench instances to test the same broker (cluster), so the start number can be 
                             planned to avoid client ID collision [default: 0]
  --num-retry-connect        number of times to retry estabilishing a connection before giving up [default: 0]
  --reconnect                max retries of reconnects. 0: disabled [default: 0]
  -S, --ssl                  ssl socket for connecting to server [default: false]
  --ssl-version              enforce tls version and implies ssl is enabled, 'tlsv1.1' | 'tlsv1.2' | 'tlsv1.3' | 
                             'tlsv1.3_nocompat'
  --cacertfile               CA certificate for server verification
  --certfile                 client certificate for authentication, if required by server
  --keyfile                  client private key for authentication, if required by server
  --ciphers                  Cipher suite for ssl/tls connection, comma separated list. e.g. 
                             TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
  --signature-algs           Signature algorithm for tlsv1.3 connection only, comma separated list. e.g. 
                             ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256
  --keyex-algs               Key exchange algorithm for tlsv1.3 connection only, comma separated list. e.g. 
                             secp384r1,secp256r1
  --quic                     QUIC transport [default: false]
  --ws                       websocket transport [default: false]
  --load-qst                 load quic session tickets from dets file
  -u, --username             username for connecting to server
  -P, --password             password for connecting to server
  -k, --keepalive            keep alive in seconds [default: 300]
  -C, --clean                clean session [default: true]
  -x, --session-expiry       Set 'Session-Expiry' for persistent sessions (seconds) [default: 0]
  -l, --lowmem               enable low mem mode, but use more CPU
  --force-major-gc-interval  interval in milliseconds in which a major GC will be forced on the bench processes.  a value of 
                             0 means disabled (default).  this only takes effect when used together with --lowmem. [default: 
                             0]
  -Q, --qoe                  set 'true' to enable QoE tracking. set 'dump' to dump QoE disklog to csv then exit [default: 
                             false]
  --qoelog                   Write QoE event logs to the QoE disklog file for post processing [default: ]
  --prometheus               Enable metrics collection via Prometheus. Usually used with --restapi to enable scraping 
                             endpoint.
  --restapi                  Enable REST API for monitoring and control. For now only serves /metrics. Can be set to IP:Port 
                             to listen on a specific IP and Port, or just Port to listen on all interfaces on that port. 
                             [default: disabled]
  --log_to                   Control where the log output goes. console: directly to the console      null: quietly, don't 
                             output any logs. [default: console]
  -t, --topic                topic subscribe, support %u, %c, %i variables
  --payload-hdrs             Handle the payload header from received message. Publish side must have the same option enabled 
                             in the same order. cnt64: Check the counter is strictly increasing. ts: publish latency 
                             counting, could be used for QoE tracking as well [default: ]
  -q, --qos                  subscribe qos [default: 0]

For example, create 50K concurrent connections at the arrival rate of 100/sec:

./emqtt_bench sub -c 50000 -i 10 -t bench/%i -q 2

Pub Benchmark

Usage: emqtt_bench pub [--help <help>] [-d <dist>] [-h [<host>]] [-p [<port>]] [-V [<version>]] [-c [<count>]]
                       [-R [<conn_rate>]] [-i [<interval>]] [--ifaddr <ifaddr>] [--prefix <prefix>] [--shortids]
                       [-n [<startnumber>]] [--num-retry-connect [<num_retry_connect>]] [-R [<conn_rate>]]
                       [--reconnect [<reconnect>]] [-S [<ssl>]] [--ssl-version <sslversion>] [--cacertfile <cacertfile>]
                       [--certfile <certfile>] [--keyfile <keyfile>] [--ciphers <ciphers>]
                       [--signature-algs <signature_algs>] [--keyex-algs <keyex_algs>] [--quic [<quic>]] [--ws [<ws>]]
                       [--load-qst <nst_dets_file>] [-u <username>] [-P <password>] [-k [<keepalive>]] [-C [<clean>]]
                       [-x [<expiry>]] [-l <lowmem>] [--force-major-gc-interval [<force_major_gc_interval>]] [-Q [<qoe>]]
                       [--qoelog [<qoelog>]] [--prometheus] [--restapi [<restapi>]] [--log_to [<log_to>]]
                       [-I [<interval_of_msg>]] [-t <topic>] [--payload-hdrs [<payload_hdrs>]] [-s [<size>]] [-m <message>]
                       [--topics-payload <topics_payload>] [-q [<qos>]] [-r [<retain>]] [-L [<limit>]] [-F [<inflight>]]
                       [-w [<wait_before_publishing>]] [--max-random-wait [<max_random_wait>]]
                       [--min-random-wait [<min_random_wait>]] [--retry-interval [<retry_interval>]]

  --help                        help information
  -d, --dist                    enable distribution port
  -h, --host                    mqtt server hostname or comma-separated hostnames [default: localhost]
  -p, --port                    mqtt server port number [default: 1883]
  -V, --version                 mqtt protocol version: 3 | 4 | 5 [default: 5]
  -c, --count                   max count of clients [default: 200]
  -R, --connrate                connection rate(/s), default: 0, fallback to use --interval [default: 0]
  -i, --interval                interval of connecting to the broker [default: 10]
  --ifaddr                      local ipaddress or interface address
  --prefix                      Client ID prefix. If not provided '$HOST_bench_(pub|sub)_$RANDOM_$N' is used, where $HOST is 
                                either the host name or the IP address provided in the --ifaddr option, $RANDOM is a random 
                                number and $N is the sequence number assigned for each client. If provided, the $RANDOM 
                                suffix will not be added.
  --shortids                    Use short client ID. If --prefix is provided, the prefix is added otherwise client ID is the 
                                assigned sequence number. [default: false]
  -n, --startnumber             The start point when assigning sequence numbers to clients. This is useful when running 
                                multiple emqtt-bench instances to test the same broker (cluster), so the start number can be 
                                planned to avoid client ID collision [default: 0]
  --num-retry-connect           number of times to retry estabilishing a connection before giving up [default: 0]
  --reconnect                   max retries of reconnects. 0: disabled [default: 0]
  -S, --ssl                     ssl socket for connecting to server [default: false]
  --ssl-version                 enforce tls version and implies ssl is enabled, 'tlsv1.1' | 'tlsv1.2' | 'tlsv1.3' | 
                                'tlsv1.3_nocompat'
  --cacertfile                  CA certificate for server verification
  --certfile                    client certificate for authentication, if required by server
  --keyfile                     client private key for authentication, if required by server
  --ciphers                     Cipher suite for ssl/tls connection, comma separated list. e.g. 
                                TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
  --signature-algs              Signature algorithm for tlsv1.3 connection only, comma separated list. e.g. 
                                ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256
  --keyex-algs                  Key exchange algorithm for tlsv1.3 connection only, comma separated list. e.g. 
                                secp384r1,secp256r1
  --quic                        QUIC transport [default: false]
  --ws                          websocket transport [default: false]
  --load-qst                    load quic session tickets from dets file
  -u, --username                username for connecting to server
  -P, --password                password for connecting to server
  -k, --keepalive               keep alive in seconds [default: 300]
  -C, --clean                   clean session [default: true]
  -x, --session-expiry          Set 'Session-Expiry' for persistent sessions (seconds) [default: 0]
  -l, --lowmem                  enable low mem mode, but use more CPU
  --force-major-gc-interval     interval in milliseconds in which a major GC will be forced on the bench processes.  a value 
                                of 0 means disabled (default).  this only takes effect when used together with --lowmem. 
                                [default: 0]
  -Q, --qoe                     set 'true' to enable QoE tracking. set 'dump' to dump QoE disklog to csv then exit [default: 
                                false]
  --qoelog                      Write QoE event logs to the QoE disklog file for post processing [default: ]
  --prometheus                  Enable metrics collection via Prometheus. Usually used with --restapi to enable scraping 
                                endpoint.
  --restapi                     Enable REST API for monitoring and control. For now only serves /metrics. Can be set to 
                                IP:Port to listen on a specific IP and Port, or just Port to listen on all interfaces on 
                                that port. [default: disabled]
  --log_to                      Control where the log output goes. console: directly to the console      null: quietly, 
                                don't output any logs. [default: console]
  -I, --interval_of_msg         interval of publishing message(ms) [default: 1000]
  -t, --topic                   topic subscribe, support %u, %c, %i, %s variables
  --payload-hdrs                 If set, add optional payload headers. cnt64: strictly increasing counter(64bit) per 
                                publisher ts: Timestamp when emit example: --payload-hdrs cnt64,ts [default: ]
  -s, --size                    payload size [default: 256]
  -m, --message                 Set the message content for publish. Either a literal message content, or path to a file 
                                with payload template specified via 'template://<file_path>'. Available variables: 
                                %TIMESTAMP%, %TIMESTAMPMS%, %TIMESTAMPUS%, %TIMESTAMPNS%, %UNIQUE%, %RANDOM%. When using 
                                'template://', --size option does not have effect except for when %RANDOM% placeholder is 
                                used.
  --topics-payload              json file defining topics and payloads
  -q, --qos                     subscribe qos [default: 0]
  -r, --retain                  retain message [default: false]
  -L, --limit                   The max message count to publish, 0 means unlimited [default: 0]
  -F, --inflight                maximum inflight messages for QoS 1 an 2, value 0 for 'infinity' [default: 1]
  -w, --wait-before-publishing  wait for all publishers to have (at least tried to) connected before starting publishing 
                                [default: false]
  --max-random-wait             maximum randomized period in ms that each publisher will wait before starting to publish 
                                (uniform distribution) [default: 0]
  --min-random-wait             minimum randomized period in ms that each publisher will wait before starting to publish 
                                (uniform distribution) [default: 0]
  --retry-interval              Publisher's resend interval (in seconds) if the expected acknowledgement for a inflight 
                                packet is not received within this interval. Default value 0 means no resend. [default: 0]

For example, create 100 connections and each publishes messages at the rate of 100 msg/sec.

./emqtt_bench pub -c 100 -I 10 -t bench/%i -s 256

Local interface

./emqtt_bench pub --ifaddr 192.168.1.10
./emqtt_bench sub --ifaddr 192.168.2.10

TLS/SSL (cliet certificate is not required by server)

./emqtt_bench sub -c 100 -i 10 -t bench/%i -p 8883 --ssl
./emqtt_bench pub -c 100 -I 10 -t bench/%i -p 8883 -s 256 --ssl

TLS/SSL (client certificate is required by server)

./emqtt_bench sub -c 100 -i 10 -t bench/%i -p 8883 --ssl --certfile path/to/client-cert.pem --keyfile path/to/client-key.pem
./emqtt_bench pub -c 100 -i 10 -t bench/%i -s 256 -p 8883 --ssl --certfile path/to/client-cert.pem --keyfile path/to/client-key.pem

Notice

You should not set '-c' option more than 64K for TCP ports limit on one source addresses, however you can send messages from multiple source IP Addresses with '--ifaddr ' such like

./emqtt_bench sub -c 200000 -t "perf/test" --ifaddr 192.168.200.18,192.168.200.19,192.168.200.20,192.168.200.21

Make sure to increase resource usage limits and expand the port range like following on Linux.

ulimit -n 200000
sudo sysctl -w net.ipv4.ip_local_port_range="1025 65534"

Author

EMQX Team.