فاز 17 · درس 22

تست بار روی API مدل‌های زبانی: چرا k6 و Locust به شما دروغ می‌گویند؟

نوع
ساختنی
زمان
حدود 75 دقیقه
زبان‌ها
Python (stdlib, toy realistic-prompt generator + latency collector)
پیش‌نیاز
فاز 17 · 08 (معیارهای استنتاج)، فاز 17 · 03 (مقیاس‌پذیری خودکار GPU)
چندین فشارسنج مکانیکی و نمایشگر آنالوگ که عقربه‌های آن‌ها فشارهای متفاوتی را در یک لوله‌کشی توزیع‌شده نشان می‌دهند
فهرست مطالب
  1. اهداف یادگیری
  2. صورت مسئله
  3. مبانی نظری
  4. تله‌ی GIL (ابزار Locust)
  5. تله‌ی یکنواختی پرامپت
  6. چهار الگوی تست بار
  7. نقشه‌ی ابزارهای سال 2026
  8. گیت SLA در CI
  9. توزیع واقعی پرامپت
  10. اعدادی که باید به خاطر بسپارید
  11. کار با کد
  12. تحویل پروژه
  13. تمرین‌ها
  14. واژگان کلیدی
  15. مطالعه‌ی بیشتر

بسیاری از تیم‌های مهندسی اندپوینت‌های مدل زبانی خود را با سناریوهای رایج ابزارهای تست بار مثل 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 استفاده می‌کند تا طول‌ها و محتواهای متنوعی شبیه‌سازی شوند.

چهار الگوی تست بار

  1. حالت پایدار (Steady-state) — نرخ درخواست بر ثانیه‌ی (RPS) ثابت به مدت 30 تا 60 دقیقه. تشخیص می‌دهد: افت کارایی نسبت به خط مبنا.
  2. شیب‌دار (Ramp) — افزایش خطی RPS از 0 تا مقدار هدف طی 15 دقیقه. تشخیص می‌دهد: نقطه‌ی شکست ظرفیت و رفتارهای غیرعادی در مرحله‌ی گرم شدن (Warm-up).
  3. جهشی (Spike) — جهش ناگهانی 3 تا 10 برابری RPS به مدت 2 دقیقه و سپس بازگشت به حالت قبل. تشخیص می‌دهد: تاخیر در مقیاس‌پذیری خودکار، اشباع صف و اثر شروع سرد (Cold-start).
  4. فرسایشی (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.
  • چهار الگوی تست: پایدار، شیب‌دار، جهشی و فرسایشی.
الگوهای باریک الگو را انتخاب کنید
LOAD PATTERNSFour load shapes catch four failures. Steady-state measures baseline throughput; ramp climbs until the breaking point; spike surges suddenly to test how fast autoscaling reacts; soak holds load for hours to surface memory leaks. Generic testers also lie when every request is identical — real traffic needs variable input length and diverse prefixes.الگوی جهشی (SPIKE)جهش ناگهانی — سنجش واکنش مقیاس‌پذیری خودکار
چهار الگوی بار مختلف، چهار نوع نقص متفاوت را آشکار می‌کنند. حالت پایدار (Steady-state) نرخ پردازش خط مبنا را می‌سنجد؛ بار افزایشی (ramp) تا نقطه شکست سیستم بالا می‌رود؛ بار جهشی (spike) ناگهان اوج می‌گیرد تا سرعت واکنش مقیاس‌پذیری خودکار را بسنجد؛ و بار مداوم (soak) بار کاری را ساعت‌ها نگه می‌دارد تا نشت‌های حافظه آشکار شوند. ابزارهای عمومی تست بار در صورتی که تمام درخواست‌ها یکسان باشند نتایج کاذب ارائه می‌دهند — ترافیک واقعی به طول ورودی متغیر و پیشوندهای متنوع نیاز دارد.

کار با کد

فایل code/main.py یک تست بار را با توزیع واقعی پرامپت شبیه‌سازی می‌کند، مقدار موثر TPOT را می‌سنجد و تله‌ی ناشی از پرامپت‌های یکنواخت را عملاً نشان می‌دهد.

تحویل پروژه

خروجی این درس فایل outputs/skill-load-test-plan.md است. این سند بر اساس حجم کاری و SLA تعیین‌شده، ابزار را انتخاب می‌کند و چهار الگوی بار را برای آن طراحی می‌نماید.

تمرین‌ها

  1. اسکریپت code/main.py را اجرا کنید. تفاوت توزیع یکنواخت را با توزیع واقعی مقایسه کنید؛ شکاف کارایی کجاست؟
  2. یک اسکریپت k6 برای گیت CI بنویسید: P95 TTFT کمتر از 800 میلی‌ثانیه با 100 کاربر هم‌زمان، به مدت 5 دقیقه.
  3. در یک تست فرسایشی، حافظه با نرخ 50 مگابایت بر ساعت افزایش پیدا می‌کند. سه دلیل احتمالی و ابزارهای پایش لازم برای تفکیک آن‌ها از یکدیگر را بنویسید.
  4. تستی با جهش بار ناگهانی از 10 به 100 RPS اجرا کنید. اگر استک عملیاتی Karpenter به همراه vLLM آماده باشد (فاز 17 · 03 + 18)، زمان بازیابی پیش‌بینی‌شده چقدر است؟
  5. ابزار 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 تا مقدار هدف طی یک بازه زمانی
جهشی «تست جهش ناگهانی» افزایش ناگهانی بار با ضریب مشخص و سپس بازگشت به مقدار اولیه
فرسایشی «تست طولانی» اجرای چندساعته برای کشف نشت حافظه

مطالعه‌ی بیشتر

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درستله‌ی GIL در تست بار مدل‌های زبانی با ابزار Locust چیست؟
  2. حین درستله‌ی یکنواختی پرامپت (prompt-uniformity trap) چیست؟
  3. حین درسدرس کدام چهار الگوی بار را پیشنهاد می‌کند؟
  4. حین درسدرس چه روشی را برای ساخت توزیع پرامپت واقع‌گرایانه پیشنهاد می‌کند؟
  5. پس از درسکدام ترکیب ابزار سال 2026 به‌عنوان بهترین گزینه برای گیت‌های SLA در CI/CD و اجراهای توزیع‌شده نیتیو کوبرنتیز معرفی شده است؟
  6. پس از درسالگوی بار مداوم (soak) چه نوع خطایی را آشکار می‌کند؟

سؤالات متداول

تله GIL در ابزار Locust هنگام تست بار مدل‌های زبانی چیست؟

در ابزار Locust فرایند توکن‌سازی روی کلاینت و زیر چتر قفل سراسری مفسر (GIL) پایتون اجرا می‌شود. در هم‌زمانی‌های بالا، توکن‌سازی پشت صف درخواست‌ها می‌ماند و این تاخیر کلاینت به اشتباه به عنوان تاخیر بین‌توکنی سرور گزارش می‌شود.

چرا تست بار با یک پرامپت تکراری در حلقه نتایج غلط می‌دهد؟

ارسال یک پرامپت ثابت باعث اصابت نزدیک به 100 درصدی به کش پیشوند (Prefix Cache) سرور می‌شود. این حالت توهم توان پردازشی بالا ایجاد می‌کند، در حالی که ترافیک واقعی طول و پیشوندهای متنوعی دارد.

تفاوت خروجی معیار TPOT بین دو ابزار GenAI-Perf و LLMPerf در چیست؟

ابزار GenAI-Perf متعلق به NVIDIA مقدار TTFT را در محاسبه تاخیر بین‌توکنی (ITL) و TPOT دخالت نمی‌دهد، اما LLMPerf آن را به حساب می‌آورد؛ به همین دلیل مقدار متفاوتی برای یک سرور گزارش می‌کنند.

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.