آزمون واقعی سرعت و صحت تشخیص — نسخه 0.10.28-acceptance.2

این ابزار اصلاح‌کنندهٔ تنظیمات نیست. درخواست صوتی واقعی به همان API می‌فرستد و
نشان می‌دهد آیا «تمام درخواست‌های این آزمون زیر ۵۰۰ میلی‌ثانیه» و «زمان بیرون
از بازه‌های اجرای موتور کمتر از ۱۰۰ میلی‌ثانیه» بوده‌اند. نتیجهٔ آزمون فقط برای
همین تعداد هم‌زمانی، فایل‌ها، کاتالوگ، سخت‌افزار و بازهٔ اندازه‌گیری معتبر است.
از میانگین سریع نمی‌توان نتیجه گرفت که همهٔ درخواست‌ها سریع‌اند.

۱. آماده‌کردن مجموعهٔ ورودی

از recognition_acceptance.example.json کپی بگیرید و مسیر فایل‌های واقعی را وارد
کنید. مسیرهای نسبی نسبت به پوشهٔ فایل JSON تفسیر می‌شوند. فایل نمونه برای اجرا
آماده نیست: صوت نمونه و شناسهٔ واقعی آهنگ عمداً در بسته قرار ندارد.

برای هر ورودی موارد زیر لازم است:
  id: نام کوتاه و یکتا با حروف لاتین/عدد و . _ -
  path: مسیر فایل صوتی محلی
  duration_seconds: مدت واقعی کلیپ بین ۴ تا ۱۸۰ ثانیه
  expected: یکی از matched یا no_match
  expected_track_ids: برای matched، شناسه‌های واقعی مجاز کاتالوگ؛ برای no_match []
  phase: measurement یا warmup
  sha256: اختیاری؛ اگر وارد شود باید با فایل تطابق داشته باشد

مدت از JSON گزارش می‌شود؛ ابزار برای هر درخواست ffprobe اجرا نمی‌کند. مدت را
پیش از آزمون درست ثبت کنید. حجم و SHA256 از خود فایل خوانده و دوباره هنگام
ارسال کنترل می‌شوند. بازگرداندن آهنگی خارج از شناسه‌های مجاز شکست صحت است؛
شناسهٔ درست در کنار یک نتیجهٔ اشتباه هم موفق محسوب نمی‌شود. اگر نمایهٔ پاسخ
کلید API فیلد TrackId را حذف کرده باشد، صحت matched تأیید نمی‌شود.

هر فایل فقط یک بار ارسال می‌شود. فایل‌های تکراری حتی با اسم دیگر و حتی بین
warmup و measurement رد می‌شوند. به فایل‌ها دادهٔ تصادفی اضافه نکنید؛ کلیپ‌های
واقعاً متفاوت شامل آهنگ‌های موجود، کلیپ دشوار و ورودی ناموجود انتخاب کنید.
این ابزار کش سرور را پاک یا غیرفعال نمی‌کند. اگر ورودی از قبل در کش باشد، آن
درخواست در گروه جدا گزارش و برای اثبات ظرفیت مستقل موتور نامعتبر می‌شود.

۲. بررسی اولیه، بدون ارسال هیچ درخواست شبکه

python3 scripts/recognition_acceptance.py \
  --manifest /root/acceptance-manifest.json \
  --base-url http://127.0.0.1:8094 \
  --concurrency 20 --requests 20 --dry-run

حالت پیش‌فرض هم dry-run است. اگر ۲۰ فایل مجزا در manifest موجود نباشد، ابزار
متوقف می‌شود؛ فایل‌ها را تکرار نمی‌کند و تعداد درخواست را پنهانی کم نمی‌کند.
نشانی باید فقط origin باشد؛ مسیر، query و نام کاربری/رمز در URL پذیرفته نیست.

۳. خواندن کلیدها بدون قرار دادن مقدار آن‌ها در خط فرمان یا گزارش

در Bash:
read -r -s -p 'API key: ' MELOYAB_API_KEY
printf '\n'
export MELOYAB_API_KEY
read -r -s -p 'Admin key (for request traces): ' MELOYAB_ADMIN_KEY
printf '\n'
export MELOYAB_ADMIN_KEY

به‌جای متغیر محیطی، --api-key-file و --admin-key-file هم قابل استفاده‌اند؛ داخل
هر فایل فقط خود کلید باشد، بدون Bearer. کلید مدیر برای خواندن گزارش درخواست
است و فقط GET /admin/requests/{request_id} پس از پایان ترافیک اجرا می‌شود.
کلید API همان کلید سرویس یا مشتری با مجوز تشخیص است. هیچ تنظیم مدیریتی تغییر
نمی‌کند. پاسخ خام شامل توکن تلگرام، لینک دانلود یا خطای خام در گزارش ذخیره نمی‌شود.

۴. یک موج محدود از ۲۰ ورودی متفاوت

python3 scripts/recognition_acceptance.py \
  --manifest /root/acceptance-manifest.json \
  --base-url http://127.0.0.1:8094 \
  --concurrency 20 --requests 20 --timeout 30 \
  --output /root/meloyab-acceptance-20.json --run

بدون --rps همهٔ ورودی‌ها برای ابتدای یک موج زمان‌بندی می‌شوند. concurrency
حداکثر درخواست واقعاً در حال ارسال/دریافت است. اگر requests بیشتر باشد، انتظار
در سمت آزمون پنهان نمی‌شود: client_queue_ms و client_scheduled_ms ثبت می‌شوند.
برای سنجش ۲۰ درخواست هم‌زمان، هر دو مقدار را ۲۰ بگذارید؛ آزمون با سقف هم‌زمانی
۸، ظرفیت ۲۰ اتصال هم‌زمان را اثبات نمی‌کند.

۵. ورود پیوسته با نرخ مشخص و مدت محدود

python3 scripts/recognition_acceptance.py \
  --manifest /root/acceptance-manifest.json \
  --base-url http://127.0.0.1:8094 \
  --concurrency 40 --rps 10 --duration 60 --timeout 30 \
  --output /root/meloyab-acceptance-rps10.json --run

این مثال به ۶۰۰ فایل measurement متفاوت نیاز دارد. duration مدت برنامهٔ ورود
است، نه دستور قطع پاسخ‌های کند. ابزار تا پایان درخواست‌های زمان‌بندی‌شده ادامه
می‌دهد و دیرکرد در اجرای زمان‌بندی را نیز حساب می‌کند. برای بار کمتر ابتدا
requests و concurrency را پایین انتخاب کنید. اجرای --run واقعاً بار ایجاد می‌کند.

برای warmup گزینهٔ --warmup N را اضافه کنید؛ N فایل متفاوت با phase=warmup لازم
است. warmup پیش از اندازه‌گیری اجرا و نتایجش جدا ثبت می‌شود. پیش‌فرض warmup=0
است تا اثر شروع سرد پنهان نشود.

۶. معنی زمان‌ها و نتیجه

client_http_ms:
  از در اختیار گرفتن ظرفیت ارسال تا دریافت کامل پاسخ؛ شامل اتصال، خواندن فایل
  محلی، آپلود، شبکه و پاسخ. منتظرماندن برای ظرفیت ارسال در این مقدار نیست.

client_scheduled_ms:
  از زمان برنامه‌ریزی‌شده تا دریافت کامل پاسخ؛ انتظار سمت تولیدکنندهٔ بار را
  نیز دارد. شرط کمتر از ۵۰۰ میلی‌ثانیه روی این مقدار اعمال می‌شود تا عقب‌ماندن تولید
  بار، بار واقعی را کمتر نشان ندهد. client_queue_ms سهم انتظار سمت آزمون است.

server_total_ms:
  duration_ms گزارش معتبر همان درخواست در سرور. شرط زیر ۵۰۰ میلی‌ثانیه روی این مقدار
  هم اعمال می‌شود. Server-Timing هدر قبل از پایان ارسال پاسخ ساخته می‌شود و
  جایگزین duration_ms نیست.

engine_critical_path_wall_ms:
  اجتماع بازه‌های واقعی تلاش موتور. در اجرای موازی، قسمت‌های هم‌پوشان فقط یک
  بار حساب می‌شوند. این مقدار شامل صف/IPC و پردازش فرادادهٔ همان تلاش موتور
  است و «زمان خالص CPU» نیست. دامنه در سرور engine_attempt_wall_union است.

server_outside_engine_ms:
  زمان کل سرور منهای اجتماع معتبر بازه‌های موتور؛ باید کمتر از ۱۰۰ ms باشد.

engine_attempt_elapsed_sum_ms:
  مجموع زمان تلاش‌ها؛ در اجرای موازی ممکن است از زمان واقعی بیشتر باشد و هرگز
  برای محاسبهٔ فاصله از زمان کل کم نمی‌شود.

server_search_wall_proxy_ms و server_outside_search_proxy_ms:
  دادهٔ تشخیصی قدیمی clip_timing_ms.search و اختلاف آن با کل؛ این‌ها به علت
  داشتن هزینهٔ dispatch و مراحل دیگر، مدرک تأیید فاصلهٔ موتور نیستند.

گزارش p50/p95/p99/max، تمام نتیجه‌ها، matched/no_match، کش/اشتراک نتیجه، خطا،
timeout و ورودی غلط را جدا نگه می‌دارد. HTTP 200 با جست‌وجوی ناقص موفق نیست؛
HTTP 503 یا timeout هم no_match سریع محسوب نمی‌شود. هیچ درخواست تشخیص دوباره
فرستاده نمی‌شود. warmup در درصدک‌های measurement نیست.

کد خروجی:
  ۰ = همهٔ درخواست‌های اندازه‌گیری صحیح، کامل، مستقل و در هر دو هدف بوده‌اند.
  ۱ = حداقل یک شکست صحت/زمان/کامل‌بودن یا استفاده از کش/اشتراک نتیجه وجود دارد.
  ۲ = تنظیم، manifest، کلید یا مسیر خروجی نامعتبر است؛ بار شروع نشده است.
  ۳ = نتیجه قابل تأیید نیست؛ مثلاً trace معتبر یا زمان دقیق بازهٔ موتور موجود نیست.

کلید مدیر اختیاری است؛ بدون آن زمان سمت مشتری گزارش می‌شود، ولی ادعای تحقق
فاصلهٔ موتور یا زمان دقیق سرور تأیید نمی‌شود. trace با تأخیر پس از پاسخ ذخیره
می‌شود؛ ابزار به طور پیش‌فرض حداکثر ۳ بار گزارش خواندنی را بررسی می‌کند.

آزمون روی 127.0.0.1 هزینهٔ اینترنت مشتری را نشان نمی‌دهد. برای سنجش تجربهٔ بیرونی
همین ابزار را روی میزبان جدا با URL واقعی اجرا کنید. اجرای تولیدکنندهٔ بار روی
خود سرور هم ممکن است منابع سرور را مصرف کند؛ مکان اجرا را هنگام مقایسه ثابت نگه دارید.
برای مقایسهٔ دو نسخه، نیاز به مجموعه‌های هم‌ارز و بررسی وضعیت کش دارید. اجراهای
دوم روی فایل‌های یکسان را به‌عنوان جست‌وجوی مستقل سریع‌تر گزارش نکنید.

خروجی JSON را برای بررسی بفرستید. این فایل شناسهٔ درخواست، SHA256 ورودی، شناسهٔ
آهنگ و آمار زمان را دارد؛ خود صوت و کلیدها در آن نیستند.
