- 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
789 lines
40 KiB
Bash
789 lines
40 KiB
Bash
#!/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 "╚══════════════════════════════════════════════════════════════════════╝"
|