WIP reproduce stats
This commit is contained in:
commit
df4116b174
6 changed files with 249 additions and 0 deletions
67
garage-latency-simple.R
Executable file
67
garage-latency-simple.R
Executable file
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/env Rscript
|
||||||
|
.libPaths(c("~/R", .libPaths()))
|
||||||
|
repo <- "https://cran.r-project.org"
|
||||||
|
|
||||||
|
if (!require(tidyverse)) install.packages("tidyverse", repos=repo); library(tidyverse)
|
||||||
|
if (!require(svglite)) install.packages("svglite", repos=repo); library(svglite)
|
||||||
|
|
||||||
|
system("mkdir -p $HOME/.local/bin")
|
||||||
|
Sys.getenv("HOME") -> home
|
||||||
|
Sys.setenv(PATH = paste(paste(home, "/go/bin", sep=""), paste(home, "/.local/bin", sep=""), Sys.getenv("PATH"), sep=":"))
|
||||||
|
system("echo $PATH")
|
||||||
|
|
||||||
|
if (!file.exists("~/.local/bin/garage")) {
|
||||||
|
system("wget https://garagehq.deuxfleurs.fr/_releases/v0.5.0/x86_64-unknown-linux-musl/garage -O $HOME/.local/bin/garage")
|
||||||
|
system("chmod +x $HOME/.local/bin/garage")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists("~/.local/bin/minio")) {
|
||||||
|
system("wget https://dl.min.io/server/minio/release/linux-amd64/minio.RELEASE.2021-11-24T23-19-33Z -O $HOME/.local/bin/minio")
|
||||||
|
system("chmod +x $HOME/.local/bin/minio")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists("~/.local/bin/mknet")) {
|
||||||
|
system("pip3 install --user git+https://git.deuxfleurs.fr/quentin/mknet")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists("~/go/bin/s3lat")) {
|
||||||
|
system("go install git.deuxfleurs.fr/quentin/s3lat@latest")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists("50ms.garage.csv")) {
|
||||||
|
system("mknet create ./mknet/single-dc.yml")
|
||||||
|
system("mknet run-all ./mknet/deploy_garage.sh")
|
||||||
|
system("mknet run dc1:dc1s1 ./mknet/bench_garage.sh")
|
||||||
|
system("mknet destroy")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists("50ms.minio.csv")) {
|
||||||
|
system("mknet create ./mknet/single-dc.yaml")
|
||||||
|
system("mknet run-all ./mknet/deploy_minio.py")
|
||||||
|
system("mknet run dc1:dc1s1 ./mknet/bench_minio.sh")
|
||||||
|
system("mknet destroy")
|
||||||
|
}
|
||||||
|
|
||||||
|
read_csv("50ms.garage.csv") %>% add_column(daemon="garage 0.5.0") -> a
|
||||||
|
read_csv("50ms.minio.csv") %>% add_column(daemon="minio RELEASE.2021-11-24T23-19-33Z") -> b
|
||||||
|
bind_rows(a,b) %>% group_by(daemon,op) %>% summarise(
|
||||||
|
time_mean = mean(time),
|
||||||
|
time_max = max(time),
|
||||||
|
time_min = min(time)
|
||||||
|
) -> c
|
||||||
|
|
||||||
|
ggplot(c, aes(x=op,y=time_mean,fill=daemon,ymin=time_min,ymax=time_max)) +
|
||||||
|
geom_bar(stat="identity", position=position_dodge(),color="black") +
|
||||||
|
geom_errorbar(position=position_dodge(.9),width=.2) +
|
||||||
|
scale_y_continuous(expand=c(0,0))+
|
||||||
|
coord_flip() +
|
||||||
|
labs(
|
||||||
|
x="S3 Endpoint",
|
||||||
|
y="Latency (ms)",
|
||||||
|
fill="Daemon",
|
||||||
|
caption="Get the code to reproduce this graph at https://git.deuxfleurs.fr/quentin/benchmarks",
|
||||||
|
title="S3 endpoint latency in a simulated geo-distributed cluster",
|
||||||
|
subtitle="100 measurements, 5 nodes, 100ms RTT + 20ms jitter between nodes\nno contention: latency is due to intra-cluster communications\ncolored bar = mean latency, error bar = min and max") +
|
||||||
|
theme_classic() +
|
||||||
|
ggsave("endpoint-latency.png", width=200, height=110, units="mm")
|
||||||
|
|
18
mknet/bench_garage.sh
Executable file
18
mknet/bench_garage.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
socat "openssl-listen:4443,\
|
||||||
|
reuseaddr,\
|
||||||
|
fork,\
|
||||||
|
verify=0,\
|
||||||
|
cert=/tmp/garage.pem" tcp4-connect:localhost:3900 &
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
export SSL=1
|
||||||
|
export SSL_INSECURE=1
|
||||||
|
export REGION=garage
|
||||||
|
export ENDPOINT=localhost:4443
|
||||||
|
export AWS_ACCESS_KEY_ID=GK4ea45d2f25091883071e0b73
|
||||||
|
export AWS_SECRET_ACCESS_KEY=334f7b0ef233571c67b302c5197e6b8c7150da1907e4e530caa82e041d725ecf
|
||||||
|
|
||||||
|
/home/quentin/go/bin/bench-garage | tee 50ms.garage.csv
|
7
mknet/bench_minio.sh
Executable file
7
mknet/bench_minio.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export ENDPOINT=[fc00:9a7a:9e::1]:9000
|
||||||
|
export AWS_ACCESS_KEY_ID=minioadmin
|
||||||
|
export AWS_SECRET_ACCESS_KEY=minioadmin
|
||||||
|
|
||||||
|
s3lat | tee 50ms.minio.csv
|
61
mknet/deploy_garage.sh
Executable file
61
mknet/deploy_garage.sh
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
GARAGE_PATH=garage
|
||||||
|
STORAGE_PATH=/tmp/garage-testnet
|
||||||
|
export RPC_SECRET=3e9abff5f9e480afbadb46a77b7a26fe0e404258f0dc3fd5386b0ba8e0ad2fba
|
||||||
|
|
||||||
|
if [ -z "$ZONE" ]; then
|
||||||
|
NODE_STORAGE_PATH=${STORAGE_PATH}/${HOST}
|
||||||
|
else
|
||||||
|
NODE_STORAGE_PATH=${STORAGE_PATH}/${ZONE}/${HOST}
|
||||||
|
fi
|
||||||
|
BOOTSTRAP_FILE=${STORAGE_PATH}/bootstrap_peer
|
||||||
|
export GARAGE_CONFIG_FILE=${NODE_STORAGE_PATH}/garage.toml
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p ${NODE_STORAGE_PATH}
|
||||||
|
cd ${NODE_STORAGE_PATH}
|
||||||
|
rm ${BOOTSTRAP_FILE} 2>/dev/null || true
|
||||||
|
|
||||||
|
cat > ${GARAGE_CONFIG_FILE} << EOF
|
||||||
|
metadata_dir = "${NODE_STORAGE_PATH}/meta"
|
||||||
|
data_dir = "${NODE_STORAGE_PATH}/data"
|
||||||
|
|
||||||
|
replication_mode = "3"
|
||||||
|
|
||||||
|
rpc_bind_addr = "[::]:3901"
|
||||||
|
rpc_public_addr = "[${IP}]:3901"
|
||||||
|
rpc_secret = "${RPC_SECRET}"
|
||||||
|
|
||||||
|
bootstrap_peers=[]
|
||||||
|
|
||||||
|
[s3_api]
|
||||||
|
s3_region = "garage"
|
||||||
|
api_bind_addr = "[::]:3900"
|
||||||
|
root_domain = ".s3.garage"
|
||||||
|
|
||||||
|
[s3_web]
|
||||||
|
bind_addr = "[::]:3902"
|
||||||
|
root_domain = ".web.garage"
|
||||||
|
index = "index.html"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
RUST_LOG=garage=debug ${GARAGE_PATH} server 2>> ${NODE_STORAGE_PATH}/logs & disown
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
CONFIG_NODE_FPATH=$(find /tmp/garage-testnet/ -maxdepth 3 -name garage.toml|head -n 1)
|
||||||
|
|
||||||
|
SELF_ID=$(${GARAGE_PATH} node id 2>/dev/null)
|
||||||
|
SHORT_ID=$(echo ${SELF_ID} | cut -c-64)
|
||||||
|
|
||||||
|
${GARAGE_PATH} -c ${CONFIG_NODE_FPATH} node connect ${SELF_ID}
|
||||||
|
${GARAGE_PATH} -c ${CONFIG_NODE_FPATH} layout assign ${SHORT_ID} -z ${ZONE:-unzonned-${HOST}} -c 1 -t ${HOST}
|
||||||
|
|
||||||
|
if [ ${CONFIG_NODE_FPATH} == ${GARAGE_CONFIG_FILE} ]; then
|
||||||
|
sleep 2
|
||||||
|
${GARAGE_PATH} layout show
|
||||||
|
${GARAGE_PATH} layout apply --version 1
|
||||||
|
fi
|
62
mknet/deploy_minio.py
Executable file
62
mknet/deploy_minio.py
Executable file
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import json, os, sys, time, pathlib, socket, shutil
|
||||||
|
|
||||||
|
STORAGE_PATH = os.path.join(os.getcwd(), '.minio-testnet')
|
||||||
|
HOSTS_PATH = os.path.join(STORAGE_PATH, 'hosts.txt')
|
||||||
|
UNIX_SOCK = os.path.join(STORAGE_PATH, 'deploy.sock')
|
||||||
|
DATA_PATH = lambda nid: os.path.join(STORAGE_PATH, 'data'+str(nid))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if int(os.environ['ID']) == 1: leader()
|
||||||
|
else: follower()
|
||||||
|
|
||||||
|
def leader():
|
||||||
|
shutil.rmtree(STORAGE_PATH, ignore_errors=True)
|
||||||
|
os.makedirs(STORAGE_PATH)
|
||||||
|
print(STORAGE_PATH)
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
sock.bind(UNIX_SOCK)
|
||||||
|
sock.listen()
|
||||||
|
|
||||||
|
n_serv = os.environ['SIZE']
|
||||||
|
fl = [ co for co, addr in [ sock.accept() for i in range(n_serv - 1) ]]
|
||||||
|
|
||||||
|
identities = [ json.loads(co.makefile().readline()) for co in fl ] + [ { "ip": os.environ['IP'], "path": make_data() } ]
|
||||||
|
print(f"ident: {identities}")
|
||||||
|
msg = f"{json.dumps(identities)}\n".encode()
|
||||||
|
[ co.send(msg) for co in fl ]
|
||||||
|
|
||||||
|
run_minio(identities)
|
||||||
|
|
||||||
|
def follower():
|
||||||
|
co = None
|
||||||
|
while True:
|
||||||
|
time.sleep(1)
|
||||||
|
try:
|
||||||
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
sock.connect(UNIX_SOCK)
|
||||||
|
co = sock.makefile()
|
||||||
|
break
|
||||||
|
except Exception as err:
|
||||||
|
print('conn failed, wait,', err)
|
||||||
|
my_identity = json.dumps({ "ip": os.environ['IP'], "path": make_data() })
|
||||||
|
sock.send(f"{my_identity}\n".encode())
|
||||||
|
identities = json.loads(co.readline())
|
||||||
|
|
||||||
|
run_minio(identities)
|
||||||
|
|
||||||
|
def make_data():
|
||||||
|
data_path = DATA_PATH(os.environ['ID'])
|
||||||
|
os.makedirs(data_path)
|
||||||
|
return data_path
|
||||||
|
|
||||||
|
def run_minio(identities):
|
||||||
|
cmd = f"minio server --console-address ':9001' --address [{os.environ['IP']}]:9000"
|
||||||
|
for ident in identities:
|
||||||
|
cmd += f" http://[{ident['ip']}]:9000{ident['path']}"
|
||||||
|
cmd += f" > {os.path.join(STORAGE_PATH, 'minio'+os.environ['ID']+'.log')} 2>&1"
|
||||||
|
print("launch: ", cmd)
|
||||||
|
os.system(cmd)
|
||||||
|
|
||||||
|
__name__ == '__main__' and main()
|
34
mknet/single-dc.yml
Normal file
34
mknet/single-dc.yml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
links:
|
||||||
|
- &fiber
|
||||||
|
bandwidth: 100M
|
||||||
|
latency: 50ms
|
||||||
|
jitter: 10ms
|
||||||
|
|
||||||
|
zones:
|
||||||
|
- &dc1
|
||||||
|
name: dc1
|
||||||
|
internal: *fiber
|
||||||
|
external: *fiber
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- name: dc1s1
|
||||||
|
zone: *dc1
|
||||||
|
- name: dc1s2
|
||||||
|
zone: *dc1
|
||||||
|
- name: dc1s3
|
||||||
|
zone: *dc1
|
||||||
|
- name: dc1s4
|
||||||
|
zone: *dc1
|
||||||
|
- name: dc1s5
|
||||||
|
zone: *dc1
|
||||||
|
|
||||||
|
global:
|
||||||
|
subnet:
|
||||||
|
base: 'fc00:9a7a:9e::'
|
||||||
|
local: 64
|
||||||
|
zone: 16
|
||||||
|
latency-offset: 3ms
|
||||||
|
upstream:
|
||||||
|
ip: fc00:9a7a:9e:ffff:ffff:ffff:ffff:ffff
|
||||||
|
conn: *fiber
|
||||||
|
|
Loading…
Reference in a new issue