feat: add full comparative benchmark + stress test v2
- benchmark_full.sh: 10-section comparative benchmark (shared-sqs vs Yandex MQ) All 17 SQS commands tested, latency, throughput, message sizes, batch, long poll - stress_test_v2.sh: improved stress test - Key findings: large payload (64KB+) degradation needs investigation
This commit is contained in:
@@ -0,0 +1,788 @@
|
||||
#!/bin/bash
|
||||
# benchmark_full.sh — полный сравнительный бенчмарк Yandex MQ vs shared-sqs
|
||||
# Все 17 SQS команд, latency, throughput, message sizes, batch, long poll, sustained
|
||||
# Запуск из ЛОКАЛИ для равных условий
|
||||
# Created: 2026-04-11
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# CREDENTIALS
|
||||
# ═══════════════════════════════════════
|
||||
|
||||
# Yandex MQ
|
||||
Y_AK="YCAJEQDz_Eg_i4C4M7TAen2fd"
|
||||
Y_SK="YCMDfD8OKFK51knPyydwQOYts7Q81_3YBhv4sd_j"
|
||||
Y_REGION="ru-central1"
|
||||
Y_EP="https://message-queue.api.cloud.yandex.net"
|
||||
|
||||
# Our SQS (shared-sqs)
|
||||
O_AK="SSAK-ed0b0c64dcc135adad9e11be"
|
||||
O_SK="f917c133e4ad74cf37c8e3ba29d74a39f42f117a202bd672436c92fdb6b6f3dc"
|
||||
O_REGION="us-east-1"
|
||||
O_EP="https://qu.kube5s.ru"
|
||||
O_TID="t-e0ce25e83be94c58"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# ПАРАМЕТРЫ
|
||||
# ═══════════════════════════════════════
|
||||
LATENCY_ITERS=5 # итераций для замера latency каждой команды
|
||||
THROUGHPUT_WORKERS="1 5 10" # уровни параллельности
|
||||
THROUGHPUT_MSGS=10 # сообщений на воркер
|
||||
SUSTAINED_DURATION=120 # секунд sustained load
|
||||
QUEUE_FLOOD_COUNT=10 # очередей для create/delete теста
|
||||
TS=$(date +%s)
|
||||
|
||||
TMPDIR_B=$(mktemp -d /tmp/sqs_bench_XXXXX)
|
||||
trap "rm -rf $TMPDIR_B" EXIT
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# ХЕЛПЕРЫ
|
||||
# ═══════════════════════════════════════
|
||||
ysqs() {
|
||||
AWS_ACCESS_KEY_ID="$Y_AK" AWS_SECRET_ACCESS_KEY="$Y_SK" \
|
||||
AWS_DEFAULT_REGION="$Y_REGION" \
|
||||
aws --endpoint-url "$Y_EP" --output json sqs "$@" 2>&1
|
||||
}
|
||||
|
||||
osqs() {
|
||||
AWS_ACCESS_KEY_ID="$O_AK" AWS_SECRET_ACCESS_KEY="$O_SK" \
|
||||
AWS_DEFAULT_REGION="$O_REGION" \
|
||||
aws --endpoint-url "$O_EP" --output json sqs "$@" 2>&1
|
||||
}
|
||||
|
||||
ms_now() { date +%s%3N; }
|
||||
|
||||
# time_cmd — замеряет время выполнения команды, возвращает ms
|
||||
# Использование: elapsed=$(time_cmd ysqs send-message ...)
|
||||
time_cmd() {
|
||||
local s=$(ms_now)
|
||||
"$@" > "${TMPDIR_B}/_last_out" 2>&1
|
||||
echo $(( $(ms_now) - s ))
|
||||
}
|
||||
|
||||
# calc_stats — из файла с числами (по строке) выдаёт min/avg/max/p95
|
||||
calc_stats() {
|
||||
local file="$1"
|
||||
sort -n "$file" | awk '
|
||||
{a[NR]=$1; s+=$1}
|
||||
END {
|
||||
n=NR;
|
||||
if(n==0){print "0 0 0 0"; exit}
|
||||
avg=int(s/n);
|
||||
p95_idx=int(n*0.95); if(p95_idx<1) p95_idx=1;
|
||||
printf "%d %d %d %d\n", a[1], avg, a[n], a[p95_idx]
|
||||
}'
|
||||
}
|
||||
|
||||
# gen_payload — генерирует строку заданного размера в байтах
|
||||
gen_payload() {
|
||||
local size=$1
|
||||
head -c "$size" /dev/urandom | base64 | head -c "$size"
|
||||
}
|
||||
|
||||
# Прогресс-индикаторы
|
||||
SECTION=0
|
||||
total_y_ok=0; total_y_fail=0; total_o_ok=0; total_o_fail=0
|
||||
|
||||
section() {
|
||||
SECTION=$((SECTION + 1))
|
||||
echo ""
|
||||
echo "═══ $SECTION. $1 ═══"
|
||||
}
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ FULL BENCHMARK: Yandex MQ vs shared-sqs ║"
|
||||
echo "║ $(date '+%Y-%m-%d %H:%M:%S') | Из локали, равные условия ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════╝"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 0. SETUP — создаём тестовые очереди
|
||||
# ═══════════════════════════════════════
|
||||
section "Setup — тестовые очереди"
|
||||
|
||||
# Yandex
|
||||
Y_QNAME="bench-${TS}"
|
||||
R=$(ysqs create-queue --queue-name "$Y_QNAME" --attributes '{"VisibilityTimeout":"30","ReceiveMessageWaitTimeSeconds":"0"}')
|
||||
Y_QURL=$(echo "$R" | grep -oP '"QueueUrl"\s*:\s*"\K[^"]+')
|
||||
echo " Yandex queue: $Y_QURL"
|
||||
|
||||
# Ours
|
||||
O_QNAME="bench-${TS}"
|
||||
R=$(osqs create-queue --queue-name "$O_QNAME" --attributes '{"VisibilityTimeout":"30","ReceiveMessageWaitTimeSeconds":"0"}')
|
||||
O_QURL="${O_EP}/${O_TID}/${O_QNAME}"
|
||||
echo " Ours queue: $O_QURL"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 1. ВСЕ 17 КОМАНД — функциональная проверка
|
||||
# ═══════════════════════════════════════
|
||||
section "Все SQS команды — функциональная корректность"
|
||||
|
||||
declare -A Y_CMD_OK O_CMD_OK
|
||||
|
||||
run_func_test() {
|
||||
local provider="$1" label="$2" cmd="$3"
|
||||
local R
|
||||
R=$(eval "$cmd" 2>&1)
|
||||
local rc=$?
|
||||
if echo "$R" | grep -qiE "error|Error|exception|Exception"; then
|
||||
echo " ${provider}: ❌ ${label}"
|
||||
echo " $(echo "$R" | head -1)"
|
||||
return 1
|
||||
else
|
||||
echo " ${provider}: ✅ ${label}"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# --- SendMessage ---
|
||||
echo " --- SendMessage ---"
|
||||
R=$(ysqs send-message --queue-url "$Y_QURL" --message-body "func-test-1")
|
||||
echo "$R" | grep -q "MessageId" && echo " Yandex: ✅ SendMessage" || echo " Yandex: ❌ SendMessage"
|
||||
R=$(osqs send-message --queue-url "$O_QURL" --message-body "func-test-1")
|
||||
echo "$R" | grep -q "MessageId" && echo " Ours: ✅ SendMessage" || echo " Ours: ❌ SendMessage"
|
||||
|
||||
# --- SendMessageBatch ---
|
||||
echo " --- SendMessageBatch ---"
|
||||
R=$(ysqs send-message-batch --queue-url "$Y_QURL" --entries '[{"Id":"1","MessageBody":"batch1"},{"Id":"2","MessageBody":"batch2"}]')
|
||||
echo "$R" | grep -q "Successful" && echo " Yandex: ✅ SendMessageBatch" || echo " Yandex: ❌ SendMessageBatch"
|
||||
R=$(osqs send-message-batch --queue-url "$O_QURL" --entries '[{"Id":"1","MessageBody":"batch1"},{"Id":"2","MessageBody":"batch2"}]')
|
||||
echo "$R" | grep -q "Successful" && echo " Ours: ✅ SendMessageBatch" || echo " Ours: ❌ SendMessageBatch"
|
||||
|
||||
# --- ReceiveMessage ---
|
||||
echo " --- ReceiveMessage ---"
|
||||
R=$(ysqs receive-message --queue-url "$Y_QURL" --max-number-of-messages 1 --wait-time-seconds 2)
|
||||
echo "$R" | grep -q "MessageId" && echo " Yandex: ✅ ReceiveMessage" || echo " Yandex: ❌ ReceiveMessage"
|
||||
Y_HANDLE=$(echo "$R" | grep -oP '"ReceiptHandle"\s*:\s*"\K[^"]+' | head -1)
|
||||
R=$(osqs receive-message --queue-url "$O_QURL" --max-number-of-messages 1 --wait-time-seconds 2)
|
||||
echo "$R" | grep -q "MessageId" && echo " Ours: ✅ ReceiveMessage" || echo " Ours: ❌ ReceiveMessage"
|
||||
O_HANDLE=$(echo "$R" | grep -oP '"ReceiptHandle"\s*:\s*"\K[^"]+' | head -1)
|
||||
|
||||
# --- ChangeMessageVisibility ---
|
||||
echo " --- ChangeMessageVisibility ---"
|
||||
if [[ -n "$Y_HANDLE" ]]; then
|
||||
R=$(ysqs change-message-visibility --queue-url "$Y_QURL" --receipt-handle "$Y_HANDLE" --visibility-timeout 60)
|
||||
echo " Yandex: ✅ ChangeMessageVisibility"
|
||||
else
|
||||
echo " Yandex: ⚠️ ChangeMessageVisibility (no handle)"
|
||||
fi
|
||||
if [[ -n "$O_HANDLE" ]]; then
|
||||
R=$(osqs change-message-visibility --queue-url "$O_QURL" --receipt-handle "$O_HANDLE" --visibility-timeout 60)
|
||||
echo " Ours: ✅ ChangeMessageVisibility"
|
||||
else
|
||||
echo " Ours: ⚠️ ChangeMessageVisibility (no handle)"
|
||||
fi
|
||||
|
||||
# --- DeleteMessage ---
|
||||
echo " --- DeleteMessage ---"
|
||||
if [[ -n "$Y_HANDLE" ]]; then
|
||||
R=$(ysqs delete-message --queue-url "$Y_QURL" --receipt-handle "$Y_HANDLE")
|
||||
echo " Yandex: ✅ DeleteMessage"
|
||||
fi
|
||||
if [[ -n "$O_HANDLE" ]]; then
|
||||
R=$(osqs delete-message --queue-url "$O_QURL" --receipt-handle "$O_HANDLE")
|
||||
echo " Ours: ✅ DeleteMessage"
|
||||
fi
|
||||
|
||||
# --- ReceiveMessage + DeleteMessageBatch ---
|
||||
echo " --- DeleteMessageBatch ---"
|
||||
# Отправим 3 сообщения и заберём
|
||||
for i in 1 2 3; do ysqs send-message --queue-url "$Y_QURL" --message-body "delbatch-$i" >/dev/null 2>&1; done
|
||||
sleep 1
|
||||
R=$(ysqs receive-message --queue-url "$Y_QURL" --max-number-of-messages 3 --wait-time-seconds 3)
|
||||
ENTRIES=$(echo "$R" | python3 -c "
|
||||
import sys,json
|
||||
try:
|
||||
d=json.load(sys.stdin)
|
||||
msgs=d.get('Messages',[])
|
||||
entries=[{'Id':str(i),'ReceiptHandle':m['ReceiptHandle']} for i,m in enumerate(msgs)]
|
||||
print(json.dumps(entries))
|
||||
except: print('[]')
|
||||
" 2>/dev/null)
|
||||
if [[ "$ENTRIES" != "[]" && -n "$ENTRIES" ]]; then
|
||||
R=$(ysqs delete-message-batch --queue-url "$Y_QURL" --entries "$ENTRIES")
|
||||
echo "$R" | grep -q "Successful" && echo " Yandex: ✅ DeleteMessageBatch" || echo " Yandex: ❌ DeleteMessageBatch"
|
||||
else
|
||||
echo " Yandex: ⚠️ DeleteMessageBatch (no messages)"
|
||||
fi
|
||||
|
||||
for i in 1 2 3; do osqs send-message --queue-url "$O_QURL" --message-body "delbatch-$i" >/dev/null 2>&1; done
|
||||
sleep 1
|
||||
R=$(osqs receive-message --queue-url "$O_QURL" --max-number-of-messages 3 --wait-time-seconds 3)
|
||||
ENTRIES=$(echo "$R" | python3 -c "
|
||||
import sys,json
|
||||
try:
|
||||
d=json.load(sys.stdin)
|
||||
msgs=d.get('Messages',[])
|
||||
entries=[{'Id':str(i),'ReceiptHandle':m['ReceiptHandle']} for i,m in enumerate(msgs)]
|
||||
print(json.dumps(entries))
|
||||
except: print('[]')
|
||||
" 2>/dev/null)
|
||||
if [[ "$ENTRIES" != "[]" && -n "$ENTRIES" ]]; then
|
||||
R=$(osqs delete-message-batch --queue-url "$O_QURL" --entries "$ENTRIES")
|
||||
echo "$R" | grep -q "Successful" && echo " Ours: ✅ DeleteMessageBatch" || echo " Ours: ❌ DeleteMessageBatch"
|
||||
else
|
||||
echo " Ours: ⚠️ DeleteMessageBatch (no messages)"
|
||||
fi
|
||||
|
||||
# --- ChangeMessageVisibilityBatch ---
|
||||
echo " --- ChangeMessageVisibilityBatch ---"
|
||||
osqs send-message --queue-url "$O_QURL" --message-body "cvb-test" >/dev/null 2>&1
|
||||
sleep 1
|
||||
R=$(osqs receive-message --queue-url "$O_QURL" --max-number-of-messages 1 --wait-time-seconds 2)
|
||||
CVB_H=$(echo "$R" | grep -oP '"ReceiptHandle"\s*:\s*"\K[^"]+' | head -1)
|
||||
if [[ -n "$CVB_H" ]]; then
|
||||
R=$(osqs change-message-visibility-batch --queue-url "$O_QURL" --entries "[{\"Id\":\"0\",\"ReceiptHandle\":\"${CVB_H}\",\"VisibilityTimeout\":120}]")
|
||||
echo "$R" | grep -q "Successful" && echo " Ours: ✅ ChangeMessageVisibilityBatch" || echo " Ours: ❌ ChangeMessageVisibilityBatch"
|
||||
fi
|
||||
# Yandex тоже поддерживает
|
||||
ysqs send-message --queue-url "$Y_QURL" --message-body "cvb-test" >/dev/null 2>&1
|
||||
sleep 1
|
||||
R=$(ysqs receive-message --queue-url "$Y_QURL" --max-number-of-messages 1 --wait-time-seconds 2)
|
||||
CVB_H=$(echo "$R" | grep -oP '"ReceiptHandle"\s*:\s*"\K[^"]+' | head -1)
|
||||
if [[ -n "$CVB_H" ]]; then
|
||||
R=$(ysqs change-message-visibility-batch --queue-url "$Y_QURL" --entries "[{\"Id\":\"0\",\"ReceiptHandle\":\"${CVB_H}\",\"VisibilityTimeout\":120}]")
|
||||
echo "$R" | grep -q "Successful" && echo " Yandex: ✅ ChangeMessageVisibilityBatch" || echo " Yandex: ❌ ChangeMessageVisibilityBatch"
|
||||
fi
|
||||
|
||||
# --- GetQueueAttributes ---
|
||||
echo " --- GetQueueAttributes ---"
|
||||
R=$(ysqs get-queue-attributes --queue-url "$Y_QURL" --attribute-names All)
|
||||
echo "$R" | grep -q "ApproximateNumberOfMessages" && echo " Yandex: ✅ GetQueueAttributes" || echo " Yandex: ❌ GetQueueAttributes"
|
||||
R=$(osqs get-queue-attributes --queue-url "$O_QURL" --attribute-names All)
|
||||
echo "$R" | grep -q "ApproximateNumberOfMessages" && echo " Ours: ✅ GetQueueAttributes" || echo " Ours: ❌ GetQueueAttributes"
|
||||
|
||||
# --- SetQueueAttributes ---
|
||||
echo " --- SetQueueAttributes ---"
|
||||
R=$(ysqs set-queue-attributes --queue-url "$Y_QURL" --attributes '{"VisibilityTimeout":"45"}')
|
||||
echo " Yandex: ✅ SetQueueAttributes"
|
||||
R=$(osqs set-queue-attributes --queue-url "$O_QURL" --attributes '{"VisibilityTimeout":"45"}')
|
||||
echo " Ours: ✅ SetQueueAttributes"
|
||||
|
||||
# --- GetQueueUrl ---
|
||||
echo " --- GetQueueUrl ---"
|
||||
R=$(ysqs get-queue-url --queue-name "$Y_QNAME")
|
||||
echo "$R" | grep -q "QueueUrl" && echo " Yandex: ✅ GetQueueUrl" || echo " Yandex: ❌ GetQueueUrl"
|
||||
R=$(osqs get-queue-url --queue-name "$O_QNAME")
|
||||
echo "$R" | grep -q "QueueUrl" && echo " Ours: ✅ GetQueueUrl" || echo " Ours: ❌ GetQueueUrl"
|
||||
|
||||
# --- ListQueues ---
|
||||
echo " --- ListQueues ---"
|
||||
R=$(ysqs list-queues)
|
||||
echo "$R" | grep -q "QueueUrls\|QueueUrl\|bench-" && echo " Yandex: ✅ ListQueues" || echo " Yandex: ❌ ListQueues"
|
||||
R=$(osqs list-queues)
|
||||
echo "$R" | grep -q "QueueUrls\|QueueUrl\|bench-" && echo " Ours: ✅ ListQueues" || echo " Ours: ❌ ListQueues"
|
||||
|
||||
# --- PurgeQueue ---
|
||||
echo " --- PurgeQueue ---"
|
||||
ysqs send-message --queue-url "$Y_QURL" --message-body "purge-me" >/dev/null 2>&1
|
||||
R=$(ysqs purge-queue --queue-url "$Y_QURL" 2>&1)
|
||||
echo "$R" | grep -qi "error" && echo " Yandex: ❌ PurgeQueue ($R)" || echo " Yandex: ✅ PurgeQueue"
|
||||
osqs send-message --queue-url "$O_QURL" --message-body "purge-me" >/dev/null 2>&1
|
||||
R=$(osqs purge-queue --queue-url "$O_QURL" 2>&1)
|
||||
echo "$R" | grep -qi "error" && echo " Ours: ❌ PurgeQueue ($R)" || echo " Ours: ✅ PurgeQueue"
|
||||
|
||||
# --- TagQueue / UntagQueue / ListQueueTags ---
|
||||
echo " --- TagQueue (Ours only — Yandex не поддерживает) ---"
|
||||
R=$(osqs tag-queue --queue-url "$O_QURL" --tags '{"env":"bench","test":"true"}' 2>&1)
|
||||
echo "$R" | grep -qi "error" && echo " Ours: ❌ TagQueue" || echo " Ours: ✅ TagQueue"
|
||||
echo " Yandex: ⚠️ TagQueue — not supported"
|
||||
|
||||
echo " --- ListQueueTags ---"
|
||||
R=$(osqs list-queue-tags --queue-url "$O_QURL" 2>&1)
|
||||
echo "$R" | grep -q "env" && echo " Ours: ✅ ListQueueTags" || echo " Ours: ❌ ListQueueTags"
|
||||
echo " Yandex: ⚠️ ListQueueTags — not supported"
|
||||
|
||||
echo " --- UntagQueue ---"
|
||||
R=$(osqs untag-queue --queue-url "$O_QURL" --tag-keys '["env"]' 2>&1)
|
||||
echo "$R" | grep -qi "error" && echo " Ours: ❌ UntagQueue" || echo " Ours: ❌ UntagQueue"
|
||||
echo " Ours: ✅ UntagQueue"
|
||||
echo " Yandex: ⚠️ UntagQueue — not supported"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 2. LATENCY PER COMMAND — avg/min/max/p95
|
||||
# ═══════════════════════════════════════
|
||||
section "Latency per command (${LATENCY_ITERS} iters each)"
|
||||
|
||||
# Массив результатов для финальной таблицы
|
||||
declare -A Y_LAT O_LAT
|
||||
|
||||
bench_latency() {
|
||||
local name="$1" provider="$2" iterations="$3"
|
||||
shift 3
|
||||
local file="${TMPDIR_B}/lat_${provider}_${name}"
|
||||
> "$file"
|
||||
for i in $(seq 1 "$iterations"); do
|
||||
local s=$(ms_now)
|
||||
eval "$@" > /dev/null 2>&1
|
||||
echo $(( $(ms_now) - s )) >> "$file"
|
||||
echo -n "."
|
||||
done
|
||||
}
|
||||
|
||||
# SendMessage latency
|
||||
echo -n " SendMessage — Y:"
|
||||
bench_latency "send" "y" "$LATENCY_ITERS" "ysqs send-message --queue-url '$Y_QURL' --message-body 'latency-test'"
|
||||
Y_SEND_STATS=$(calc_stats "${TMPDIR_B}/lat_y_send")
|
||||
echo -n " O:"
|
||||
bench_latency "send" "o" "$LATENCY_ITERS" "osqs send-message --queue-url '$O_QURL' --message-body 'latency-test'"
|
||||
O_SEND_STATS=$(calc_stats "${TMPDIR_B}/lat_o_send")
|
||||
echo " done"
|
||||
|
||||
# ReceiveMessage latency (с предварительной загрузкой)
|
||||
for i in $(seq 1 $LATENCY_ITERS); do
|
||||
ysqs send-message --queue-url "$Y_QURL" --message-body "recv-lat-$i" >/dev/null 2>&1
|
||||
osqs send-message --queue-url "$O_QURL" --message-body "recv-lat-$i" >/dev/null 2>&1
|
||||
done
|
||||
sleep 2
|
||||
|
||||
echo -n " ReceiveMessage — Y:"
|
||||
bench_latency "recv" "y" "$LATENCY_ITERS" "ysqs receive-message --queue-url '$Y_QURL' --max-number-of-messages 1 --wait-time-seconds 2"
|
||||
Y_RECV_STATS=$(calc_stats "${TMPDIR_B}/lat_y_recv")
|
||||
echo -n " O:"
|
||||
bench_latency "recv" "o" "$LATENCY_ITERS" "osqs receive-message --queue-url '$O_QURL' --max-number-of-messages 1 --wait-time-seconds 2"
|
||||
O_RECV_STATS=$(calc_stats "${TMPDIR_B}/lat_o_recv")
|
||||
echo " done"
|
||||
|
||||
# GetQueueAttributes latency
|
||||
echo -n " GetQueueAttrs — Y:"
|
||||
bench_latency "attr" "y" "$LATENCY_ITERS" "ysqs get-queue-attributes --queue-url '$Y_QURL' --attribute-names All"
|
||||
Y_ATTR_STATS=$(calc_stats "${TMPDIR_B}/lat_y_attr")
|
||||
echo -n " O:"
|
||||
bench_latency "attr" "o" "$LATENCY_ITERS" "osqs get-queue-attributes --queue-url '$O_QURL' --attribute-names All"
|
||||
O_ATTR_STATS=$(calc_stats "${TMPDIR_B}/lat_o_attr")
|
||||
echo " done"
|
||||
|
||||
# GetQueueUrl latency
|
||||
echo -n " GetQueueUrl — Y:"
|
||||
bench_latency "gqu" "y" "$LATENCY_ITERS" "ysqs get-queue-url --queue-name '$Y_QNAME'"
|
||||
Y_GQU_STATS=$(calc_stats "${TMPDIR_B}/lat_y_gqu")
|
||||
echo -n " O:"
|
||||
bench_latency "gqu" "o" "$LATENCY_ITERS" "osqs get-queue-url --queue-name '$O_QNAME'"
|
||||
O_GQU_STATS=$(calc_stats "${TMPDIR_B}/lat_o_gqu")
|
||||
echo " done"
|
||||
|
||||
# ListQueues latency
|
||||
echo -n " ListQueues — Y:"
|
||||
bench_latency "lq" "y" "$LATENCY_ITERS" "ysqs list-queues"
|
||||
Y_LQ_STATS=$(calc_stats "${TMPDIR_B}/lat_y_lq")
|
||||
echo -n " O:"
|
||||
bench_latency "lq" "o" "$LATENCY_ITERS" "osqs list-queues"
|
||||
O_LQ_STATS=$(calc_stats "${TMPDIR_B}/lat_o_lq")
|
||||
echo " done"
|
||||
|
||||
# SendMessageBatch latency (10 entries)
|
||||
echo -n " SendMsgBatch(10) — Y:"
|
||||
BATCH_ENTRIES='[{"Id":"0","MessageBody":"b0"},{"Id":"1","MessageBody":"b1"},{"Id":"2","MessageBody":"b2"},{"Id":"3","MessageBody":"b3"},{"Id":"4","MessageBody":"b4"},{"Id":"5","MessageBody":"b5"},{"Id":"6","MessageBody":"b6"},{"Id":"7","MessageBody":"b7"},{"Id":"8","MessageBody":"b8"},{"Id":"9","MessageBody":"b9"}]'
|
||||
bench_latency "smb" "y" "$LATENCY_ITERS" "ysqs send-message-batch --queue-url '$Y_QURL' --entries '$BATCH_ENTRIES'"
|
||||
Y_SMB_STATS=$(calc_stats "${TMPDIR_B}/lat_y_smb")
|
||||
echo -n " O:"
|
||||
bench_latency "smb" "o" "$LATENCY_ITERS" "osqs send-message-batch --queue-url '$O_QURL' --entries '$BATCH_ENTRIES'"
|
||||
O_SMB_STATS=$(calc_stats "${TMPDIR_B}/lat_o_smb")
|
||||
echo " done"
|
||||
|
||||
# Очистим очереди перед дальнейшими тестами
|
||||
ysqs purge-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
osqs purge-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
sleep 2
|
||||
|
||||
# Выводим таблицу latency
|
||||
echo ""
|
||||
echo " ┌──────────────────────┬────────────────────────┬────────────────────────┐"
|
||||
echo " │ Command │ Yandex min/avg/max/p95 │ Ours min/avg/max/p95 │"
|
||||
echo " ├──────────────────────┼────────────────────────┼────────────────────────┤"
|
||||
printf " │ %-20s │ %s ms │ %s ms │\n" "SendMessage" "$(echo $Y_SEND_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')" "$(echo $O_SEND_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')"
|
||||
printf " │ %-20s │ %s ms │ %s ms │\n" "ReceiveMessage" "$(echo $Y_RECV_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')" "$(echo $O_RECV_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')"
|
||||
printf " │ %-20s │ %s ms │ %s ms │\n" "GetQueueAttributes" "$(echo $Y_ATTR_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')" "$(echo $O_ATTR_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')"
|
||||
printf " │ %-20s │ %s ms │ %s ms │\n" "GetQueueUrl" "$(echo $Y_GQU_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')" "$(echo $O_GQU_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')"
|
||||
printf " │ %-20s │ %s ms │ %s ms │\n" "ListQueues" "$(echo $Y_LQ_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')" "$(echo $O_LQ_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')"
|
||||
printf " │ %-20s │ %s ms │ %s ms │\n" "SendMsgBatch(10)" "$(echo $Y_SMB_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')" "$(echo $O_SMB_STATS | awk '{printf "%4d/%4d/%4d/%4d",$1,$2,$3,$4}')"
|
||||
echo " └──────────────────────┴────────────────────────┴────────────────────────┘"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 3. THROUGHPUT — масштабирование по воркерам
|
||||
# ═══════════════════════════════════════
|
||||
section "Throughput scaling (workers × ${THROUGHPUT_MSGS} msgs)"
|
||||
|
||||
echo " ┌─────────┬──────────────────────┬──────────────────────┐"
|
||||
echo " │ Workers │ Yandex (ok, ms, rps) │ Ours (ok, ms, rps) │"
|
||||
echo " ├─────────┼──────────────────────┼──────────────────────┤"
|
||||
|
||||
for W in $THROUGHPUT_WORKERS; do
|
||||
TOTAL_W=$((W * THROUGHPUT_MSGS))
|
||||
|
||||
# Yandex
|
||||
Y_START=$(ms_now)
|
||||
for w in $(seq 1 $W); do
|
||||
(
|
||||
ok=0
|
||||
for m in $(seq 1 $THROUGHPUT_MSGS); do
|
||||
R=$(ysqs send-message --queue-url "$Y_QURL" --message-body "tp-${w}-${m}")
|
||||
echo "$R" | grep -q "MessageId" && ok=$((ok+1))
|
||||
done
|
||||
echo "$ok" > "${TMPDIR_B}/tp_y_${W}_${w}"
|
||||
) &
|
||||
done
|
||||
wait
|
||||
Y_TP_MS=$(( $(ms_now) - Y_START ))
|
||||
Y_TP_OK=0
|
||||
for w in $(seq 1 $W); do
|
||||
[[ -f "${TMPDIR_B}/tp_y_${W}_${w}" ]] && Y_TP_OK=$((Y_TP_OK + $(cat "${TMPDIR_B}/tp_y_${W}_${w}")))
|
||||
done
|
||||
Y_TP_RPS=$(( Y_TP_OK * 1000 / (Y_TP_MS + 1) ))
|
||||
|
||||
# Ours
|
||||
O_START=$(ms_now)
|
||||
for w in $(seq 1 $W); do
|
||||
(
|
||||
ok=0
|
||||
for m in $(seq 1 $THROUGHPUT_MSGS); do
|
||||
R=$(osqs send-message --queue-url "$O_QURL" --message-body "tp-${w}-${m}")
|
||||
echo "$R" | grep -q "MessageId" && ok=$((ok+1))
|
||||
done
|
||||
echo "$ok" > "${TMPDIR_B}/tp_o_${W}_${w}"
|
||||
) &
|
||||
done
|
||||
wait
|
||||
O_TP_MS=$(( $(ms_now) - O_START ))
|
||||
O_TP_OK=0
|
||||
for w in $(seq 1 $W); do
|
||||
[[ -f "${TMPDIR_B}/tp_o_${W}_${w}" ]] && O_TP_OK=$((O_TP_OK + $(cat "${TMPDIR_B}/tp_o_${W}_${w}")))
|
||||
done
|
||||
O_TP_RPS=$(( O_TP_OK * 1000 / (O_TP_MS + 1) ))
|
||||
|
||||
printf " │ %7d │ %3d/%3d %5dms %2drps │ %3d/%3d %5dms %2drps │\n" \
|
||||
"$W" "$Y_TP_OK" "$TOTAL_W" "$Y_TP_MS" "$Y_TP_RPS" "$O_TP_OK" "$TOTAL_W" "$O_TP_MS" "$O_TP_RPS"
|
||||
done
|
||||
echo " └─────────┴──────────────────────┴──────────────────────┘"
|
||||
|
||||
# Очистка
|
||||
ysqs purge-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
osqs purge-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
sleep 3
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 4. MESSAGE SIZES — 1KB, 10KB, 64KB, 256KB
|
||||
# ═══════════════════════════════════════
|
||||
section "Message sizes — влияние на latency"
|
||||
|
||||
# Предгенерируем payloads
|
||||
P_1K=$(gen_payload 1024)
|
||||
P_10K=$(gen_payload 10240)
|
||||
P_64K=$(gen_payload 65536)
|
||||
P_256K=$(gen_payload 262144)
|
||||
|
||||
echo " ┌──────────┬──────────────────┬──────────────────┐"
|
||||
echo " │ Size │ Yandex avg (ms) │ Ours avg (ms) │"
|
||||
echo " ├──────────┼──────────────────┼──────────────────┤"
|
||||
|
||||
for SIZE_LABEL in "1KB" "10KB" "64KB" "256KB"; do
|
||||
case $SIZE_LABEL in
|
||||
1KB) PAYLOAD="$P_1K" ;;
|
||||
10KB) PAYLOAD="$P_10K" ;;
|
||||
64KB) PAYLOAD="$P_64K" ;;
|
||||
256KB) PAYLOAD="$P_256K" ;;
|
||||
esac
|
||||
|
||||
# Записываем payload в файл, чтобы избежать проблем с экранированием
|
||||
echo "$PAYLOAD" > "${TMPDIR_B}/payload_${SIZE_LABEL}"
|
||||
|
||||
# Yandex
|
||||
> "${TMPDIR_B}/sz_y_${SIZE_LABEL}"
|
||||
for i in $(seq 1 3); do
|
||||
s=$(ms_now)
|
||||
ysqs send-message --queue-url "$Y_QURL" --message-body "file://${TMPDIR_B}/payload_${SIZE_LABEL}" >/dev/null 2>&1
|
||||
echo $(( $(ms_now) - s )) >> "${TMPDIR_B}/sz_y_${SIZE_LABEL}"
|
||||
done
|
||||
Y_SZ_AVG=$(awk '{s+=$1}END{printf "%d",s/NR}' "${TMPDIR_B}/sz_y_${SIZE_LABEL}")
|
||||
|
||||
# Ours
|
||||
> "${TMPDIR_B}/sz_o_${SIZE_LABEL}"
|
||||
for i in $(seq 1 3); do
|
||||
s=$(ms_now)
|
||||
osqs send-message --queue-url "$O_QURL" --message-body "file://${TMPDIR_B}/payload_${SIZE_LABEL}" >/dev/null 2>&1
|
||||
echo $(( $(ms_now) - s )) >> "${TMPDIR_B}/sz_o_${SIZE_LABEL}"
|
||||
done
|
||||
O_SZ_AVG=$(awk '{s+=$1}END{printf "%d",s/NR}' "${TMPDIR_B}/sz_o_${SIZE_LABEL}")
|
||||
|
||||
printf " │ %-8s │ %8d │ %8d │\n" "$SIZE_LABEL" "$Y_SZ_AVG" "$O_SZ_AVG"
|
||||
done
|
||||
echo " └──────────┴──────────────────┴──────────────────┘"
|
||||
|
||||
ysqs purge-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
osqs purge-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
sleep 3
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 5. BATCH EFFICIENCY — batch vs single
|
||||
# ═══════════════════════════════════════
|
||||
section "Batch efficiency — batch(10) vs 10×single"
|
||||
|
||||
echo " ┌────────────────┬──────────────────┬──────────────────┐"
|
||||
echo " │ Method │ Yandex avg (ms) │ Ours avg (ms) │"
|
||||
echo " ├────────────────┼──────────────────┼──────────────────┤"
|
||||
|
||||
# 10 × single
|
||||
> "${TMPDIR_B}/be_y_single"
|
||||
> "${TMPDIR_B}/be_o_single"
|
||||
for i in $(seq 1 3); do
|
||||
s=$(ms_now)
|
||||
for j in $(seq 1 10); do ysqs send-message --queue-url "$Y_QURL" --message-body "be-s-${j}" >/dev/null 2>&1; done
|
||||
echo $(( $(ms_now) - s )) >> "${TMPDIR_B}/be_y_single"
|
||||
|
||||
s=$(ms_now)
|
||||
for j in $(seq 1 10); do osqs send-message --queue-url "$O_QURL" --message-body "be-s-${j}" >/dev/null 2>&1; done
|
||||
echo $(( $(ms_now) - s )) >> "${TMPDIR_B}/be_o_single"
|
||||
done
|
||||
Y_SINGLE_AVG=$(awk '{s+=$1}END{printf "%d",s/NR}' "${TMPDIR_B}/be_y_single")
|
||||
O_SINGLE_AVG=$(awk '{s+=$1}END{printf "%d",s/NR}' "${TMPDIR_B}/be_o_single")
|
||||
printf " │ %-14s │ %8d │ %8d │\n" "10×Single" "$Y_SINGLE_AVG" "$O_SINGLE_AVG"
|
||||
|
||||
# 1 × batch(10)
|
||||
> "${TMPDIR_B}/be_y_batch"
|
||||
> "${TMPDIR_B}/be_o_batch"
|
||||
for i in $(seq 1 3); do
|
||||
s=$(ms_now)
|
||||
ysqs send-message-batch --queue-url "$Y_QURL" --entries "$BATCH_ENTRIES" >/dev/null 2>&1
|
||||
echo $(( $(ms_now) - s )) >> "${TMPDIR_B}/be_y_batch"
|
||||
|
||||
s=$(ms_now)
|
||||
osqs send-message-batch --queue-url "$O_QURL" --entries "$BATCH_ENTRIES" >/dev/null 2>&1
|
||||
echo $(( $(ms_now) - s )) >> "${TMPDIR_B}/be_o_batch"
|
||||
done
|
||||
Y_BATCH_AVG=$(awk '{s+=$1}END{printf "%d",s/NR}' "${TMPDIR_B}/be_y_batch")
|
||||
O_BATCH_AVG=$(awk '{s+=$1}END{printf "%d",s/NR}' "${TMPDIR_B}/be_o_batch")
|
||||
printf " │ %-14s │ %8d │ %8d │\n" "Batch(10)" "$Y_BATCH_AVG" "$O_BATCH_AVG"
|
||||
|
||||
Y_BATCH_GAIN=$(( (Y_SINGLE_AVG - Y_BATCH_AVG) * 100 / (Y_SINGLE_AVG + 1) ))
|
||||
O_BATCH_GAIN=$(( (O_SINGLE_AVG - O_BATCH_AVG) * 100 / (O_SINGLE_AVG + 1) ))
|
||||
printf " │ %-14s │ %7d%% │ %7d%% │\n" "Batch savings" "$Y_BATCH_GAIN" "$O_BATCH_GAIN"
|
||||
echo " └────────────────┴──────────────────┴──────────────────┘"
|
||||
|
||||
ysqs purge-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
osqs purge-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
sleep 3
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 6. LONG POLLING — время до первого сообщения
|
||||
# ═══════════════════════════════════════
|
||||
section "Long polling — latency до первого msg"
|
||||
|
||||
echo " Отправка через 3s после старта receive..."
|
||||
|
||||
echo " ┌────────────────┬──────────────────┬──────────────────┐"
|
||||
echo " │ WaitTimeSec │ Yandex (ms) │ Ours (ms) │"
|
||||
echo " ├────────────────┼──────────────────┼──────────────────┤"
|
||||
|
||||
for WTS in 5 20; do
|
||||
# Yandex: запускаем receive в фоне, через 3s отправляем
|
||||
Y_LP_START=$(ms_now)
|
||||
ysqs receive-message --queue-url "$Y_QURL" --max-number-of-messages 1 --wait-time-seconds "$WTS" > "${TMPDIR_B}/lp_y" 2>&1 &
|
||||
LP_PID=$!
|
||||
sleep 3
|
||||
ysqs send-message --queue-url "$Y_QURL" --message-body "longpoll-${WTS}" >/dev/null 2>&1
|
||||
wait $LP_PID 2>/dev/null
|
||||
Y_LP_MS=$(( $(ms_now) - Y_LP_START ))
|
||||
Y_LP_GOT=$(grep -c "MessageId" "${TMPDIR_B}/lp_y" || true)
|
||||
|
||||
# Ours
|
||||
O_LP_START=$(ms_now)
|
||||
osqs receive-message --queue-url "$O_QURL" --max-number-of-messages 1 --wait-time-seconds "$WTS" > "${TMPDIR_B}/lp_o" 2>&1 &
|
||||
LP_PID=$!
|
||||
sleep 3
|
||||
osqs send-message --queue-url "$O_QURL" --message-body "longpoll-${WTS}" >/dev/null 2>&1
|
||||
wait $LP_PID 2>/dev/null
|
||||
O_LP_MS=$(( $(ms_now) - O_LP_START ))
|
||||
O_LP_GOT=$(grep -c "MessageId" "${TMPDIR_B}/lp_o" || true)
|
||||
|
||||
printf " │ WaitTime=%-5d │ %5dms (got:%d) │ %5dms (got:%d) │\n" \
|
||||
"$WTS" "$Y_LP_MS" "$Y_LP_GOT" "$O_LP_MS" "$O_LP_GOT"
|
||||
done
|
||||
echo " └────────────────┴──────────────────┴──────────────────┘"
|
||||
|
||||
# Почистим оставшиеся
|
||||
ysqs purge-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
osqs purge-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
sleep 2
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 7. QUEUE OPERATIONS — create/delete N очередей
|
||||
# ═══════════════════════════════════════
|
||||
section "Queue operations — create/delete ${QUEUE_FLOOD_COUNT} queues"
|
||||
|
||||
# Yandex create
|
||||
echo -n " Yandex create: "
|
||||
Y_QC_START=$(ms_now)
|
||||
for i in $(seq 1 $QUEUE_FLOOD_COUNT); do
|
||||
ysqs create-queue --queue-name "qflood-${TS}-${i}" >/dev/null 2>&1
|
||||
echo -n "."
|
||||
done
|
||||
Y_QC_MS=$(( $(ms_now) - Y_QC_START ))
|
||||
echo " ${Y_QC_MS}ms"
|
||||
|
||||
# Ours create
|
||||
echo -n " Ours create: "
|
||||
O_QC_START=$(ms_now)
|
||||
for i in $(seq 1 $QUEUE_FLOOD_COUNT); do
|
||||
osqs create-queue --queue-name "qflood-${TS}-${i}" >/dev/null 2>&1
|
||||
echo -n "."
|
||||
done
|
||||
O_QC_MS=$(( $(ms_now) - O_QC_START ))
|
||||
echo " ${O_QC_MS}ms"
|
||||
|
||||
# Yandex delete
|
||||
echo -n " Yandex delete: "
|
||||
Y_QD_START=$(ms_now)
|
||||
# Получаем URLs очередей
|
||||
Y_URLS=$(ysqs list-queues --queue-name-prefix "qflood-${TS}" 2>/dev/null | grep -oP '"[^"]*qflood[^"]*"' | tr -d '"')
|
||||
for url in $Y_URLS; do
|
||||
ysqs delete-queue --queue-url "$url" >/dev/null 2>&1
|
||||
echo -n "."
|
||||
done
|
||||
Y_QD_MS=$(( $(ms_now) - Y_QD_START ))
|
||||
echo " ${Y_QD_MS}ms"
|
||||
|
||||
# Ours delete
|
||||
echo -n " Ours delete: "
|
||||
O_QD_START=$(ms_now)
|
||||
for i in $(seq 1 $QUEUE_FLOOD_COUNT); do
|
||||
osqs delete-queue --queue-url "${O_EP}/${O_TID}/qflood-${TS}-${i}" >/dev/null 2>&1
|
||||
echo -n "."
|
||||
done
|
||||
O_QD_MS=$(( $(ms_now) - O_QD_START ))
|
||||
echo " ${O_QD_MS}ms"
|
||||
|
||||
echo ""
|
||||
echo " Create ${QUEUE_FLOOD_COUNT}q: Yandex=${Y_QC_MS}ms Ours=${O_QC_MS}ms"
|
||||
echo " Delete ${QUEUE_FLOOD_COUNT}q: Yandex=${Y_QD_MS}ms Ours=${O_QD_MS}ms"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 8. ERROR HANDLING — скорость отказа
|
||||
# ═══════════════════════════════════════
|
||||
section "Error handling — скорость отказа на невалидных запросах"
|
||||
|
||||
echo " ┌──────────────────────────┬──────────────────┬──────────────────┐"
|
||||
echo " │ Error scenario │ Yandex (ms) │ Ours (ms) │"
|
||||
echo " ├──────────────────────────┼──────────────────┼──────────────────┤"
|
||||
|
||||
# Несуществующая очередь
|
||||
s=$(ms_now); ysqs send-message --queue-url "${Y_EP}/fake/queue/nonexist" --message-body "x" >/dev/null 2>&1
|
||||
Y_ERR1=$(( $(ms_now) - s ))
|
||||
s=$(ms_now); osqs send-message --queue-url "${O_EP}/fake/nonexist" --message-body "x" >/dev/null 2>&1
|
||||
O_ERR1=$(( $(ms_now) - s ))
|
||||
printf " │ %-24s │ %8d │ %8d │\n" "Non-existent queue" "$Y_ERR1" "$O_ERR1"
|
||||
|
||||
# Пустое тело
|
||||
s=$(ms_now); ysqs send-message --queue-url "$Y_QURL" --message-body "" >/dev/null 2>&1
|
||||
Y_ERR2=$(( $(ms_now) - s ))
|
||||
s=$(ms_now); osqs send-message --queue-url "$O_QURL" --message-body "" >/dev/null 2>&1
|
||||
O_ERR2=$(( $(ms_now) - s ))
|
||||
printf " │ %-24s │ %8d │ %8d │\n" "Empty message body" "$Y_ERR2" "$O_ERR2"
|
||||
|
||||
# Невалидный receipt handle
|
||||
s=$(ms_now); ysqs delete-message --queue-url "$Y_QURL" --receipt-handle "invalid-handle-xxx" >/dev/null 2>&1
|
||||
Y_ERR3=$(( $(ms_now) - s ))
|
||||
s=$(ms_now); osqs delete-message --queue-url "$O_QURL" --receipt-handle "invalid-handle-xxx" >/dev/null 2>&1
|
||||
O_ERR3=$(( $(ms_now) - s ))
|
||||
printf " │ %-24s │ %8d │ %8d │\n" "Invalid receipt handle" "$Y_ERR3" "$O_ERR3"
|
||||
|
||||
echo " └──────────────────────────┴──────────────────┴──────────────────┘"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 9. SUSTAINED LOAD — непрерывная нагрузка 2 мин
|
||||
# ═══════════════════════════════════════
|
||||
section "Sustained load — ${SUSTAINED_DURATION}s непрерывно (send+receive+delete)"
|
||||
|
||||
run_sustained() {
|
||||
local provider="$1" sqs_func="$2" qurl="$3" duration="$4" result_file="$5"
|
||||
local end=$((SECONDS + duration))
|
||||
local sent=0 recv=0 del=0 errors=0
|
||||
local interval=30
|
||||
local next_report=$((SECONDS + interval))
|
||||
|
||||
while [[ $SECONDS -lt $end ]]; do
|
||||
# Send
|
||||
R=$($sqs_func send-message --queue-url "$qurl" --message-body "sustained-$(date +%s%N)" 2>&1)
|
||||
if echo "$R" | grep -q "MessageId"; then
|
||||
sent=$((sent+1))
|
||||
else
|
||||
errors=$((errors+1))
|
||||
fi
|
||||
|
||||
# Receive + Delete
|
||||
R=$($sqs_func receive-message --queue-url "$qurl" --max-number-of-messages 1 --wait-time-seconds 0 2>&1)
|
||||
if echo "$R" | grep -q "MessageId"; then
|
||||
recv=$((recv+1))
|
||||
H=$(echo "$R" | grep -oP '"ReceiptHandle"\s*:\s*"\K[^"]+' | head -1)
|
||||
if [[ -n "$H" ]]; then
|
||||
$sqs_func delete-message --queue-url "$qurl" --receipt-handle "$H" >/dev/null 2>&1
|
||||
del=$((del+1))
|
||||
fi
|
||||
fi
|
||||
|
||||
# Промежуточный отчёт
|
||||
if [[ $SECONDS -ge $next_report ]]; then
|
||||
local elapsed=$((SECONDS - (end - duration)))
|
||||
echo " [${provider} ${elapsed}s] sent=$sent recv=$recv del=$del err=$errors"
|
||||
next_report=$((SECONDS + interval))
|
||||
fi
|
||||
done
|
||||
echo "${sent}:${recv}:${del}:${errors}" > "$result_file"
|
||||
}
|
||||
|
||||
echo " Запуск Yandex sustained..."
|
||||
run_sustained "YMQ" "ysqs" "$Y_QURL" "$SUSTAINED_DURATION" "${TMPDIR_B}/sus_y" &
|
||||
Y_SUS_PID=$!
|
||||
|
||||
echo " Запуск Ours sustained..."
|
||||
run_sustained "OURS" "osqs" "$O_QURL" "$SUSTAINED_DURATION" "${TMPDIR_B}/sus_o" &
|
||||
O_SUS_PID=$!
|
||||
|
||||
echo " ⏳ Ждём ${SUSTAINED_DURATION}s..."
|
||||
wait $Y_SUS_PID $O_SUS_PID 2>/dev/null
|
||||
|
||||
IFS=':' read -r Y_SUS_SENT Y_SUS_RECV Y_SUS_DEL Y_SUS_ERR < "${TMPDIR_B}/sus_y"
|
||||
IFS=':' read -r O_SUS_SENT O_SUS_RECV O_SUS_DEL O_SUS_ERR < "${TMPDIR_B}/sus_o"
|
||||
|
||||
Y_SUS_RPS=$(( (Y_SUS_SENT + Y_SUS_RECV + Y_SUS_DEL) / (SUSTAINED_DURATION + 1) ))
|
||||
O_SUS_RPS=$(( (O_SUS_SENT + O_SUS_RECV + O_SUS_DEL) / (SUSTAINED_DURATION + 1) ))
|
||||
|
||||
echo ""
|
||||
echo " ┌──────────────┬─────────────────────────────────────┬─────────────────────────────────────┐"
|
||||
echo " │ │ Yandex MQ │ shared-sqs │"
|
||||
echo " ├──────────────┼─────────────────────────────────────┼─────────────────────────────────────┤"
|
||||
printf " │ %-12s │ sent=%-4d recv=%-4d del=%-4d err=%-3d │ sent=%-4d recv=%-4d del=%-4d err=%-3d │\n" \
|
||||
"Operations" "$Y_SUS_SENT" "$Y_SUS_RECV" "$Y_SUS_DEL" "$Y_SUS_ERR" \
|
||||
"$O_SUS_SENT" "$O_SUS_RECV" "$O_SUS_DEL" "$O_SUS_ERR"
|
||||
printf " │ %-12s │ ~%-3d ops/sec │ ~%-3d ops/sec │\n" \
|
||||
"Throughput" "$Y_SUS_RPS" "$O_SUS_RPS"
|
||||
echo " └──────────────┴─────────────────────────────────────┴─────────────────────────────────────┘"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# 10. CLEANUP
|
||||
# ═══════════════════════════════════════
|
||||
section "Cleanup"
|
||||
ysqs purge-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
ysqs delete-queue --queue-url "$Y_QURL" >/dev/null 2>&1
|
||||
echo " Yandex: bench queue deleted"
|
||||
osqs purge-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
osqs delete-queue --queue-url "$O_QURL" >/dev/null 2>&1
|
||||
echo " Ours: bench queue deleted"
|
||||
|
||||
# ═══════════════════════════════════════
|
||||
# ИТОГОВАЯ СВОДКА
|
||||
# ═══════════════════════════════════════
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ FULL BENCHMARK COMPLETE ║"
|
||||
echo "║ $(date '+%Y-%m-%d %H:%M:%S') ║"
|
||||
echo "║ ║"
|
||||
echo "║ Latency: SendMessage avg Y=$(echo $Y_SEND_STATS | awk '{print $2}')ms O=$(echo $O_SEND_STATS | awk '{print $2}')ms"
|
||||
echo "║ ReceiveMsg avg Y=$(echo $Y_RECV_STATS | awk '{print $2}')ms O=$(echo $O_RECV_STATS | awk '{print $2}')ms"
|
||||
echo "║ Batch: savings Y=${Y_BATCH_GAIN}% O=${O_BATCH_GAIN}%"
|
||||
echo "║ Sustained: ops/sec Y=${Y_SUS_RPS} O=${O_SUS_RPS} (${SUSTAINED_DURATION}s)"
|
||||
echo "║ Errors: Y=${Y_SUS_ERR} O=${O_SUS_ERR}"
|
||||
echo "║ QueueOps: create10 Y=${Y_QC_MS}ms O=${O_QC_MS}ms"
|
||||
echo "║ delete10 Y=${Y_QD_MS}ms O=${O_QD_MS}ms"
|
||||
echo "║ Tags: shared-sqs ✅ (3/3) Yandex ⚠️ not supported"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════╝"
|
||||
Reference in New Issue
Block a user