The project contains a bunch of folders:
benchmark-client
which is ago
command line benchmarkbenchmark-server
a simplego
http server that is responsible for running thebenchmark-client
process under the hood and returns the resultscontainernet-environment
- the test containernet setup that should start theetcd
database andbenchmark-server
with arbitrary network topology and resources limit
The benchmark server is responsible for receiving http requests with the following body payload:
{
"endpoints": "comma separated list of etcd instances with their respective ports e.g. localhost:2379,localhost:2380",
"clients": 2, // a number of clients that should be used for performing a single benchmark,
"total": 1000, // the number of total requests that should be performed against the database, either read or write
"conns": 100 // number of concurrent connections
}
read
benchmark specific parameters:
{
"key": "key to query",
"endRange": "the range's end key when testing range performance",
"consistency": "consistencty type of read query (l - Linearizable or s - Serializable)"
}
write
benchmark specific parameters:
{
"keySize": "size of the key in bytes",
"valSize": "size of the value in bytes",
"sequentialKeys": "should the keys be sequential",
"targetLeader": "should it query only the leader instance"
}
There are 2 endpoints available:
/benchmark/read
- tests the read performance (operationrange
)/benchmark/write
- tests the write performance (operationput
)
Example call with curl
:
# watchout when using docker-compose setup as the localhost domain will map to `etcd`
# read benchmark
curl -d '{"endpoints": "10.0.0.251:2379", "clients": 5, "conns": 5, "total": 1000, "key": "foo", "endRange": "foo3", "consistency": "l"}' http://localhost:8080/benchmark/read
# write benchmark
curl -d '{"endpoints": "10.0.0.251:2379", "clients": 5, "conns": 5, "total": 1000, "keySize": 4, "valSize": 64, "targetLeader": true, "sequentialKeys": true}' http://localhost:8080/benchmark/read
- Install containernet https://github.com/containernet/containernet#option-1-bare-metal-installation
- Run the following command
cd containernet
sudo python3 setup.py install
- Build docker images
./build.sh
- Run etcd and benchamrk in containernet.
sudo python3 containernet-environment/main.py -c [ config_file_path ]
Containernet main.py
file accepts configuration files in a .json format. Example file:
[
{
"ip": "10.0.0.251", // instance ip
"mem": "100m", // memory limits
"cpus": "8", // cpu limits in cpu units
"bandwidth": 1000, // bandwith limits
"link_delay": "3ms"
},
{
"ip": "10.0.0.252",
"mem": "100m",
"cpus": "8",
"bandwidth": 1000,
"link_delay": "3ms"
}
]
- Check cluster state:
etcd1 etcdctl member list
- Then you can test it using:
curl -d '{"endpoints": "10.0.0.251:2379", "clients": 5, "conns": 5, "total": 1000, "key": "foo", "endRange": "foo3", "consistency": "l"}' http://localhost:8080/benchmark/read
Project includes benchmarking script. You can run it with:
sudo ./test.sh [ config_file_path ] [ result_file_name ]
Script is going to build docker images at first. Then it is going to set up Containernet environment and run benchmark using a set of scenarios.
Scenarios consist of a series of key writes followed by a series of reads. Write scenarios include single and multiclient writes with multiple connections openned for between 1000 and 100000 keys. What is more they cover also cluster and leader only writes. Read scenarios test etcd performance based on the consistency of operation, meaning that some of them require whole quorum to agree while the rest don't.
Benchmark results are saved to csv file under the name that is passed in one of the arguments. CSV contain columns that describe both benchmark results and scenario settings:
TestType | ClusterSize | RequestCount | ClientCount | ConnectionCount | KeySize | ValueSize | Consistency | Total | Slowest | Fastest | Average | Stddev | Requests/sec | 10% | 25% | 50% | 75% | 90% | 95% |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
write | 2 | 100000 | 1000 | 100 | 4 | 64 | - | 144.9626 | 5.6176 | 0.6311 | 1.4391 | 0.2509 | 689.8333 | 1.3289 | 1.3804 | 1.4166 | 1.4381 | 1.4567 | 1.4728 |
write | 2 | 100000 | 1000 | 100 | 8 | 256 | - | 302.7955 | 15.0167 | 0.6634 | 3.0120 | 0.8257 | 330.2559 | 2.6280 | 2.7675 | 2.8599 | 2.9412 | 2.9901 | 5.3955 |
read | 2 | 100000 | 100 | 100 | - | - | l | 276.3772 | 0.9761 | 0.2372 | 0.2762 | 0.0219 | 361.8243 | 0.2586 | 0.2657 | 0.2759 | 0.2842 | 0.2918 | 0.2976 |
read | 2 | 100000 | 100 | 100 | - | - | s | 264.3478 | 0.9440 | 0.2220 | 0.2642 | 0.0189 | 378.2895 | 0.2557 | 0.2584 | 0.2626 | 0.2682 | 0.2736 | 0.2769 |
After the benchmark executes, the Containernet is shut down and topology is deleted.