بسیاری از تیمهای مهندسی اندپوینتهای مدل زبانی خود را با سناریوهای رایج ابزارهای تست بار مثل k6 یا Locust میسنجند و پس از موفقیت در تست، سیستم را به پروداکشن میبرند؛ اما در ترافیک واقعی با کاربران کمتر، سرویس ناگهان زیر بار فلج میشود. معماری مدلهای زبانی به دلیل خروجیهای استریمینگ، توکنسازی بلادرنگ و تفاوت طول پاسخها، قواعد کاملاً متفاوتی با وبسرویسهای معمولی دارد.
در این درس بررسی میکنیم که چرا ابزارهای سنتی معیارهای تاخیر را اشتباه نشان میدهند، چگونه تلههای انباشتگی GIL و کش پیشوندها (Prefix Caching) نتایج را تحریف میکنند و چطور باید با ابزارهایی مانند LLMPerf یا نسخههای جدید k6، سناریوهای بار واقعی طراحی کرد.
ابزارهای سنتی تست بار برای پاسخهای استریمینگ، طول متغیر خروجی، معیارهای سطح توکن یا اشباع پردازندهی گرافیکی (GPU saturation) طراحی نشده بودند. دو تلهی بزرگ بیشتر تیمها را به دردسر میاندازد. اول، تلهی قفل سراسری مفسر (GIL trap): ابزار Locust اندازهگیری در سطح توکن را زیر چتر GIL پایتون انجام میدهد؛ جایی که توکنسازی زیر بار همزمانی سنگین، با تولید درخواست رقابت میکند. انباشت صف توکنسازی باعث میشود تاخیر بینتوکنی (Inter-Token Latency) گزارششده بهشدت بالا برود؛ در واقع کلاینت گلوگاه است، نه سرور. دوم، تلهی یکنواختی پرامپت (Prompt-uniformity trap): فرستادن پرامپتهای یکسان در یک حلقه، فقط یک نقطه از توزیع توکنها را میسنجد؛ در حالی که ترافیک واقعی طول متغیر و تطابق پیشوندهای متنوعی دارد. ابزار LLMPerf این مشکل را با پرچمهای
--mean-input-tokensو--stddev-input-tokensحل میکند. دستهبندی ابزارها در سال 2026: ابزارهای تخصصی مدلهای زبانی (GenAI-Perf، LLMPerf، LLM-Locust، guidellm) برای دقت در سطح توکن؛ ترکیب k6 نسخه 2026.1.0 همراه با k6 Operator نسخه 1.0 GA (سپتامبر 2025) که استریمینگ را میفهمد، توزیعشده و بومی کوبرنتیز است (از طریق منابع سفارشی TestRun/PrivateLoadZone) و بهترین انتخاب برای گیتهای CI/CD به شمار میرود؛ ابزار Vegeta برای اشباع با نرخ ثابت و بر پایهی Go؛ و Locust نسخه 2.43.3 فقط بهشرط استفاده از افزونهی LLM-Locust برای استریمینگ. الگوهای بار: حالت پایدار (Steady-state)، شیبدار (Ramp)، جهشی (Spike برای آزمودن مقیاسپذیری خودکار) و فرسایشی (Soak برای کشف نشت حافظه).
اهداف یادگیری
- توضیح دو ضدالگوی رایج (تلهی GIL و تلهی یکنواختی پرامپت) که باعث میشوند ابزارهای تست بار عمومی دربارهی APIهای مدلهای زبانی آمار غلط بدهند.
- انتخاب ابزار مناسب برای هر هدف: LLMPerf (اجرای بنچمارک)، k6 همراه با افزونهی استریمینگ (گیت CI)، guidellm (سنجش دادههای ساختگی در مقیاس بزرگ) و GenAI-Perf (ابزار مرجع NVIDIA).
- طراحی چهار الگوی بار (پایدار، شیبدار، جهشی و فرسایشی) و نام بردن از نوع خرابی یا خطایی که هرکدام به دام میاندازند.
- ساخت یک توزیع واقعی پرامپت با میانگین و انحراف معیار توکنهای ورودی، بهجای طول ثابت.
صورت مسئله
اندپوینت مدل زبانی خود را با ابزار k6 زیر بار 500 کاربر همزمان تست کردهاید؛ سیستم دوام آورده و شما هم سرویس را تحویل دادهاید. اما در محیط عملیاتی (پروداکشن)، سرویس با تنها 200 کاربر واقعی از پا درمیآید: تاخیر تا دریافت اولین توکن (P99 TTFT) سر به فلک میکشد و پردازندههای گرافیکی به سقف مصرف میچسبند.
اینجا دو اتفاق افتاده است. اول اینکه k6 تعداد 500 پرامپت کاملاً یکسان فرستاده؛ در نتیجه قابلیتهای یکیکردن درخواستها (Request-coalescing) و کش پیشوند (Prefix caching) این توهم را ساختهاند که سرور در حال انجام 500 رمزگشایی (Decode) همزمان است، در حالی که در عمل فقط یک درخواست را پردازش میکرد. دوم اینکه k6 تاخیر بینتوکنی را در پاسخهای استریمینگ آنطور که چشم کاربر حس میکند اندازه نمیگیرد؛ k6 صرفاً یک اتصال HTTP میبیند، نه 500 توکنی را که با فواصل زمانی متغیر از راه میرسند.
تست بار برای مدلهای زبانی تخصص کاملاً مستقلی است.
مبانی نظری
تلهی GIL (ابزار Locust)
ابزار Locust با پایتون اجرا میشود و توکنسازی را سمت کلاینت و زیر چتر GIL انجام میدهد. زیر بار همزمانی سنگین، فرایند توکنسازی پشت صف تولید درخواست میماند. بنابراین تاخیر بینتوکنی گزارششده، تاخیر انباشتگی توکنسازی سمت کلاینت را هم به حساب میآورد. شما فکر میکنید سرور کند است؛ در حالی که مشکل از بستر آزمایشی است.
راهکار: افزونهی LLM-Locust فرایند توکنسازی را به فرایندهای مجزا منتقل میکند؛ یا اینکه میتوانید از یک بستر آزمایشی مبتنی بر زبانهای کامپایلری استفاده کنید (مثل k6، یا LLMPerf که از tokenizers.rs بهره میبرد).
تلهی یکنواختی پرامپت
همهی ابزارهای شناختهشدهی تست بار اجازه میدهند فقط یک پرامپت را پیکربندی کنید. در یک تستِ چرخهای با 10,000 تکرار، دقیقاً همان پرامپت پشت سر هم فرستاده میشود. سرور هر بار همان پیشوند را میبیند؛ در نتیجه نرخ اصابت به کش پیشوند به 100% نزدیک میشود و نرخ پردازش عالی به نظر میرسد.
راهکار: نمونهبرداری از یک توزیع پرامپت. ابزار LLMPerf از پرچمهای --mean-input-tokens 500 --stddev-input-tokens 150 استفاده میکند تا طولها و محتواهای متنوعی شبیهسازی شوند.
چهار الگوی تست بار
- حالت پایدار (Steady-state) — نرخ درخواست بر ثانیهی (RPS) ثابت به مدت 30 تا 60 دقیقه. تشخیص میدهد: افت کارایی نسبت به خط مبنا.
- شیبدار (Ramp) — افزایش خطی RPS از 0 تا مقدار هدف طی 15 دقیقه. تشخیص میدهد: نقطهی شکست ظرفیت و رفتارهای غیرعادی در مرحلهی گرم شدن (Warm-up).
- جهشی (Spike) — جهش ناگهانی 3 تا 10 برابری RPS به مدت 2 دقیقه و سپس بازگشت به حالت قبل. تشخیص میدهد: تاخیر در مقیاسپذیری خودکار، اشباع صف و اثر شروع سرد (Cold-start).
- فرسایشی (Soak) — بار پایدار به مدت 4 تا 8 ساعت. تشخیص میدهد: نشت حافظه (Memory leak)، ناپایداری استخر اتصالات و سرریز ابزارهای مشاهدهپذیری.
نقشهی ابزارهای سال 2026
LLMPerf (از Anyscale) — بر پایهی پایتون ولی با توکنسازی متکی بر Rust. پشتیبانی از میانگین و انحراف معیار برای پرامپتها. آگاه از استریمینگ. بهترین گزینهی پیشفرض برای ارزیابیهای کارایی.
NVIDIA GenAI-Perf — ابزار مرجع NVIDIA. از کلاینت Triton استفاده میکند و معیارهای سنجش کاملی دارد. دقت کنید که تاخیر بینتوکنی (ITL) در این ابزار شامل TTFT نمیشود؛ ولی در LLMPerf شامل آن است. بنابراین این دو ابزار برای یک سرور یکسان، زمان به ازای هر توکن خروجی (TPOT) متفاوتی گزارش میدهند.
LLM-Locust (از TrueFoundry) — افزونهای برای Locust که تلهی GIL را برطرف میکند. همان DSL آشنای Locust همراه با معیارهای استریمینگ.
guidellm — بنچمارک ترکیبی و مصنوعی در مقیاس وسیع.
k6 نسخه 2026.1.0 همراه با k6 Operator نسخه 1.0 GA (سپتامبر 2025):
- خود k6 (مبتنی بر Go، کامپایلشده و بدون GIL) معیارهای سنجش سازگار با استریمینگ را اضافه کرده است.
- ابزار k6 Operator از منابع سفارشی TestRun و PrivateLoadZone برای تستهای توزیعشده و بومی در کوبرنتیز استفاده میکند.
- بهترین گزینه برای گیتهای CI/CD و تستهای SLA.
Vegeta — مبتنی بر Go و سادهتر از k6. ابزاری برای اشباع با نرخ ثابت HTTP. مدلهای زبانی را نمیفهمد، ولی برای تست درگاه (Gateway) و محدودیت نرخ (Rate-limit) عالی است.
Locust نسخه 2.43.3 خام — برای مدلهای زبانی گرفتار تلهی GIL میشود؛ استفاده از آن فقط با افزونهی LLM-Locust مجاز است.
گیت SLA در CI
ابزار k6 را روی هر پولریکوئست (PR) با این تنظیمات اجرا کنید:
- 30 تا 50 بار تکرار، هر بار با RPS خط مبنا.
- شروط گیت: صدکهای P50 و P95 تاخیر اولین توکن (TTFT)، خطاهای 5xx زیر 5%، و مقدار TPOT زیر آستانه.
- در صورت نقض هر شرط، فرایند بیلد متوقف شود (Break the build).
توزیع واقعی پرامپت
توزیع را بر اساس نمونههای واقعی ترافیک بسازید (اگر در دسترس دارید) یا از توزیعهای منتشرشده کمک بگیرید (مثلاً پرامپتهای ShareGPT برای گفتوگو، یا HumanEval برای کدنویسی). میانگین و انحراف معیار را به LLMPerf بدهید. از ارسال یک پرامپت تکراری در حلقه به هر قیمتی دوری کنید.
اعدادی که باید به خاطر بسپارید
- نسخهی 1.0 GA ابزار k6 Operator: سپتامبر 2025.
- نسخهی 2026.1.0 ابزار k6: معیارهای آگاه از استریمینگ.
- اجرای استاندارد LLMPerf: بین 100 تا 1000 درخواست با همزمانی مشخص.
- گیت استاندارد CI: بین 30 تا 50 تکرار به ازای هر PR.
- چهار الگوی تست: پایدار، شیبدار، جهشی و فرسایشی.
کار با کد
فایل code/main.py یک تست بار را با توزیع واقعی پرامپت شبیهسازی میکند، مقدار موثر TPOT را میسنجد و تلهی ناشی از پرامپتهای یکنواخت را عملاً نشان میدهد.
تحویل پروژه
خروجی این درس فایل outputs/skill-load-test-plan.md است. این سند بر اساس حجم کاری و SLA تعیینشده، ابزار را انتخاب میکند و چهار الگوی بار را برای آن طراحی مینماید.
تمرینها
- اسکریپت
code/main.pyرا اجرا کنید. تفاوت توزیع یکنواخت را با توزیع واقعی مقایسه کنید؛ شکاف کارایی کجاست؟ - یک اسکریپت k6 برای گیت CI بنویسید: P95 TTFT کمتر از 800 میلیثانیه با 100 کاربر همزمان، به مدت 5 دقیقه.
- در یک تست فرسایشی، حافظه با نرخ 50 مگابایت بر ساعت افزایش پیدا میکند. سه دلیل احتمالی و ابزارهای پایش لازم برای تفکیک آنها از یکدیگر را بنویسید.
- تستی با جهش بار ناگهانی از 10 به 100 RPS اجرا کنید. اگر استک عملیاتی Karpenter به همراه vLLM آماده باشد (فاز 17 · 03 + 18)، زمان بازیابی پیشبینیشده چقدر است؟
- ابزار GenAI-Perf برای یک سرور یکسان مقدار TPOT=6ms و ابزار LLMPerf مقدار TPOT=11ms را گزارش میدهد. علت را توضیح دهید.
واژگان کلیدی
| اصطلاح | باور عامیانه | معنای دقیق فنی |
|---|---|---|
| LLMPerf | «بستر آزمایشی مدلهای زبانی» | ابزار بنچمارک توسعهدادهشده توسط Anyscale با پشتیبانی از استریمینگ |
| GenAI-Perf | «ابزار NVIDIA» | بستر آزمایشی مرجع انویدیا |
| LLM-Locust | «Locust برای مدلهای زبانی» | افزونهای برای Locust جهت رفع تلهی GIL |
| guidellm | «بنچمارک دادههای ساختگی» | ابزاری برای ارزیابی بار مصنوعی در مقیاس بزرگ |
| k6 Operator | «k6 برای کوبرنتیز» | ابزار k6 توزیعشده بر پایهی منابع سفارشی (CRD) |
| تلهی GIL | «سربار کلاینت پایتون» | انباشت صف توکنسازی که باعث افزایش کاذب تاخیر گزارششده میشود |
| تلهی یکنواختی پرامپت | «دروغ پرامپت تکی» | ارسال مکرر یک پرامپت که با اصابت دائم به کش، نرخ پردازش را بالا نشان میدهد |
| حالت پایدار | «بار ثابت» | درخواست ثابت بر ثانیه به مدت N دقیقه |
| شیبدار | «افزایش خطی» | بالا بردن تدریجی بار از 0 تا مقدار هدف طی یک بازه زمانی |
| جهشی | «تست جهش ناگهانی» | افزایش ناگهانی بار با ضریب مشخص و سپس بازگشت به مقدار اولیه |
| فرسایشی | «تست طولانی» | اجرای چندساعته برای کشف نشت حافظه |
