grok2api / test /test_concurrency.sh
JXJBing's picture
Upload 45 files
1a9e2c2 verified
#!/bin/bash
# Grok2API ๅนถๅ‘ๆต‹่ฏ•่„šๆœฌ๏ผˆShell็‰ˆๆœฌ๏ผ‰
# ไฝฟ็”จ curl ๅ’Œ GNU parallel ่ฟ›่กŒๅนถๅ‘ๆต‹่ฏ•
set -e
# ้…็ฝฎ
BASE_URL="${BASE_URL:-http://localhost:8000}"
API_KEY="${API_KEY:-}"
CONCURRENCY="${CONCURRENCY:-10}"
TOTAL_REQUESTS="${TOTAL_REQUESTS:-50}"
# ้ขœ่‰ฒ
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${NC}"
echo -e "${BLUE}โ•‘ Grok2API ๅนถๅ‘ๆ€ง่ƒฝๆต‹่ฏ•ๅทฅๅ…ท (Shell็‰ˆ) โ•‘${NC}"
echo -e "${BLUE}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
echo ""
echo -e "${GREEN}๐Ÿ”— ๆต‹่ฏ•็›ฎๆ ‡:${NC} $BASE_URL"
echo -e "${GREEN}๐Ÿ”‘ API Key:${NC} ${API_KEY:-(ๆœช่ฎพ็ฝฎ)}"
echo -e "${GREEN}๐Ÿ“Š ๅนถๅ‘ๆ•ฐ:${NC} $CONCURRENCY"
echo -e "${GREEN}๐Ÿ“ˆ ๆ€ป่ฏทๆฑ‚ๆ•ฐ:${NC} $TOTAL_REQUESTS"
echo ""
# ๆฃ€ๆŸฅไพ่ต–
if ! command -v curl &> /dev/null; then
echo -e "${RED}โŒ ้”™่ฏฏ: ้œ€่ฆๅฎ‰่ฃ… curl${NC}"
exit 1
fi
# ๅˆ›ๅปบไธดๆ—ถ็›ฎๅฝ•
TMP_DIR=$(mktemp -d)
trap "rm -rf $TMP_DIR" EXIT
# ๅ•ไธช่ฏทๆฑ‚ๅ‡ฝๆ•ฐ
test_request() {
local request_id=$1
local start_time=$(date +%s.%N)
# ๆž„ๅปบ่ฏทๆฑ‚
local headers="Content-Type: application/json"
if [ -n "$API_KEY" ]; then
headers="${headers}\nAuthorization: Bearer ${API_KEY}"
fi
local response=$(curl -s -w "\n%{http_code}\n%{time_total}" \
-X POST "${BASE_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
${API_KEY:+-H "Authorization: Bearer $API_KEY"} \
-d "{
\"model\": \"grok-3-fast\",
\"messages\": [{\"role\": \"user\", \"content\": \"ๆต‹่ฏ•่ฏทๆฑ‚ #${request_id}๏ผŒ่ฏท็ฎ€็Ÿญๅ›žๅคOK\"}],
\"stream\": false,
\"max_tokens\": 10
}" 2>&1)
local http_code=$(echo "$response" | tail -n 2 | head -n 1)
local time_total=$(echo "$response" | tail -n 1)
# ่ฎฐๅฝ•็ป“ๆžœ
echo "${request_id},${http_code},${time_total}" >> "$TMP_DIR/results.csv"
# ๆ˜พ็คบ่ฟ›ๅบฆ
echo -ne "\r ่ฟ›ๅบฆ: ${request_id}/${TOTAL_REQUESTS}"
}
# ๅฏผๅ‡บๅ‡ฝๆ•ฐไพ› parallel ไฝฟ็”จ
export -f test_request
export BASE_URL API_KEY TMP_DIR
# ๆธ…็ฉบ็ป“ๆžœๆ–‡ไปถ
echo "id,status,time" > "$TMP_DIR/results.csv"
echo -e "${YELLOW}๐Ÿš€ ๅผ€ๅง‹ๅนถๅ‘ๆต‹่ฏ•...${NC}"
START_TIME=$(date +%s.%N)
# ไฝฟ็”จ GNU parallel๏ผˆๅฆ‚ๆžœๅฏ็”จ๏ผ‰๏ผŒๅฆๅˆ™ไฝฟ็”จ็ฎ€ๅ•ๅพช็Žฏ
if command -v parallel &> /dev/null; then
seq 1 $TOTAL_REQUESTS | parallel -j $CONCURRENCY test_request {}
else
# ็ฎ€ๅ•็š„ๅŽๅฐไปปๅŠกๅนถๅ‘
for i in $(seq 1 $TOTAL_REQUESTS); do
test_request $i &
# ๆŽงๅˆถๅนถๅ‘ๆ•ฐ
if (( i % CONCURRENCY == 0 )); then
wait
fi
done
wait
fi
END_TIME=$(date +%s.%N)
TOTAL_TIME=$(echo "$END_TIME - $START_TIME" | bc)
echo -e "\n"
# ็ปŸ่ฎก็ป“ๆžœ
echo -e "${BLUE}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
echo -e "${BLUE}๐Ÿ“ˆ ๆต‹่ฏ•็ป“ๆžœ็ปŸ่ฎก${NC}"
echo -e "${BLUE}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
# ็ปŸ่ฎกๆˆๅŠŸ/ๅคฑ่ดฅ
SUCCESS_COUNT=$(awk -F',' '$2 == 200 {count++} END {print count+0}' "$TMP_DIR/results.csv")
ERROR_COUNT=$((TOTAL_REQUESTS - SUCCESS_COUNT))
echo -e " ๆต‹่ฏ•ๆ—ถ้—ด: ${TOTAL_TIME}s"
echo -e " ๆ€ป่ฏทๆฑ‚ๆ•ฐ: ${TOTAL_REQUESTS}"
echo -e " ๅนถๅ‘ๆ•ฐ: ${CONCURRENCY}"
echo ""
echo -e " ๆˆๅŠŸ่ฏทๆฑ‚: ${GREEN}${SUCCESS_COUNT}${NC} ($(echo "scale=1; $SUCCESS_COUNT * 100 / $TOTAL_REQUESTS" | bc)%)"
echo -e " ๅคฑ่ดฅ่ฏทๆฑ‚: ${RED}${ERROR_COUNT}${NC} ($(echo "scale=1; $ERROR_COUNT * 100 / $TOTAL_REQUESTS" | bc)%)"
echo ""
# ่ฎก็ฎ—ๅžๅ้‡
THROUGHPUT=$(echo "scale=2; $TOTAL_REQUESTS / $TOTAL_TIME" | bc)
echo -e " ๅžๅ้‡: ${GREEN}${THROUGHPUT}${NC} req/s"
echo ""
# ๅปถ่ฟŸ็ปŸ่ฎก๏ผˆๅช็ปŸ่ฎกๆˆๅŠŸ็š„่ฏทๆฑ‚๏ผ‰
if [ $SUCCESS_COUNT -gt 0 ]; then
echo -e " ๅปถ่ฟŸ็ปŸ่ฎก:"
# ๆๅ–ๆˆๅŠŸ่ฏทๆฑ‚็š„ๅปถ่ฟŸๆ—ถ้—ด
awk -F',' '$2 == 200 {print $3}' "$TMP_DIR/results.csv" | sort -n > "$TMP_DIR/latencies.txt"
MIN=$(head -n 1 "$TMP_DIR/latencies.txt" | awk '{printf "%.0f", $1*1000}')
MAX=$(tail -n 1 "$TMP_DIR/latencies.txt" | awk '{printf "%.0f", $1*1000}')
AVG=$(awk '{sum+=$1; count++} END {printf "%.0f", sum/count*1000}' "$TMP_DIR/latencies.txt")
# P50
P50_LINE=$((SUCCESS_COUNT / 2))
P50=$(sed -n "${P50_LINE}p" "$TMP_DIR/latencies.txt" | awk '{printf "%.0f", $1*1000}')
# P95
P95_LINE=$(echo "scale=0; $SUCCESS_COUNT * 0.95 / 1" | bc)
P95=$(sed -n "${P95_LINE}p" "$TMP_DIR/latencies.txt" | awk '{printf "%.0f", $1*1000}')
# P99
P99_LINE=$(echo "scale=0; $SUCCESS_COUNT * 0.99 / 1" | bc)
P99=$(sed -n "${P99_LINE}p" "$TMP_DIR/latencies.txt" | awk '{printf "%.0f", $1*1000}')
echo -e " ๆœ€ๅฐ: ${MIN}ms"
echo -e " ๅนณๅ‡: ${AVG}ms"
echo -e " ๆœ€ๅคง: ${MAX}ms"
echo -e " P50: ${P50}ms"
echo -e " P95: ${P95}ms"
echo -e " P99: ${P99}ms"
fi
echo -e "${BLUE}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
# ๆ€ง่ƒฝ่ฏ„็บง
echo -e "${YELLOW}๐ŸŽฏ ๆ€ง่ƒฝ่ฏ„็บง:${NC}"
if (( $(echo "$THROUGHPUT >= 100" | bc -l) )); then
RATING="โญโญโญโญโญ ไผ˜็ง€"
elif (( $(echo "$THROUGHPUT >= 60" | bc -l) )); then
RATING="โญโญโญโญ ่‰ฏๅฅฝ"
elif (( $(echo "$THROUGHPUT >= 30" | bc -l) )); then
RATING="โญโญโญ ไธญ็ญ‰"
elif (( $(echo "$THROUGHPUT >= 10" | bc -l) )); then
RATING="โญโญ ่พƒไฝŽ"
else
RATING="โญ ้œ€ไผ˜ๅŒ–"
fi
echo -e " ๅžๅ้‡ (${THROUGHPUT} req/s): ${RATING}"
echo ""
echo -e "${GREEN}โœ… ๆต‹่ฏ•ๅฎŒๆˆ๏ผ${NC}"