تصور کنید کاربر دکمهای را میزند و ناگهان تمام صفحه، از انیمیشنها گرفته تا نشانگر موس، برای چند میلیثانیه یخ میزند. این اتفاق دقیقاً همان دلیلی است که باعث میشود قابلیتهای هوش مصنوعی در سمت کاربر (Client-side)، حتی با وجود مدلهای سریع، کند و آزاردهنده به نظر برسند. هرچ elapsed-time یک مدل هوش مصنوعی ممکن است سریع باشد، اما یک فراخونی همگام (Synchronous) واحد میتواند رشته اصلی (Main Thread) مرورگر را برای صدها میلیثانیه قفل کند و رابط کاربری را کاملاً غیرپاسخگو سازد.
طبق گزارش فنی منتشر شده در dev.to در تاریخ ۲۱ ژوئیه ۲۰۲۶، این رفتار «مسدودکننده» (Blocking) دلیل اصلی این است که ویژگیهای AI در سمت کلاینت، صرفنظر از سرعت واقعی مدل، کند احساس میشوند. این گزارش تأکید میکند که مشکل اصلی نه سرعت پردازش مدل، بلکه نحوه تعامل آن با مرورگر است.
همانطور که در تحلیلهای قبلی ما دربارهی بهینهسازی مدلهای لبه اشاره کردیم، مدیریت منابع در مرورگر بسیار حساستر از محیط سرور است. در این بستر، استنتاج (Inference) — که شبیه لحظه آشپزی واقعی است، نه دورهی آموزش آشپز — اگر روی رشته اصلی اجرا شود، تمام پردازشهای بصری را متوقف میکند. این چالشها یادآور مواردی است که در آن خطاهای پنهان در کدهای تولیدشده توسط AI باعث کاهش سرعت در نسخههای موبایل شدهاند و تجربه کاربر را مختل کردهاند.
گلوگاه رشته اصلی (Main Thread Bottleneck)
برای توسعهدهندگانی که از TensorFlow.js، ONNX.js یا ابزارهای مبتنی بر WebAssembly استفاده میکنند، اجرای مستقیم استنتاج در یک React Event Handler وسوسهبرانگیز است. اما چون جاوااسکریپت تکرشتهای (Single-threaded) است، مرورگر نمیتواند در حالی که CPU در حال محاسبه وزنهای مدل است، انیمیشنها را بهروز کند یا ورودیهای کاربر را پردازش نماید.
این وضعیت یک پارادوکس ایجاد میکند: نشانگر در حال بارگذاری (Loading Spinner) هرگز ظاهر نمیشود، چون همان رشتهای که باید آن را رندر کند، توسط مدل اشغال شده است. یک پیادهسازی ساده و ناشیانه معمولاً به این صورت است: ابتدا فراخوانی setLoading(true)، سپس اجرای model.predict(inputData) و در نهایت فراخوانی setLoading(false). از آنجایی که model.predict به صورت همگام اجرا میشود، CPU را میرباید. در نتیجه، اسپینر یا هرگز رندر نمیشود یا تنها پس از پایان تسک مسدودکننده ظاهر میگردد، که منجر به سردرگمی کاربر و ощущение «هنگ کردن» اپلیکیشن میشود.

معماری برای استنتاج غیرمسدودکننده
به نقل از مستندات dev.to، راهکار قطعی برای این مشکل، تغییر معماری به سمت اجرای غیرمسدودکننده است. موثرترین روش، انتقال مدل به Web Workers است؛ ابزاری که اجازه میدهد هوش مصنوعی در یک رشته پسزمینه مجزا اجرا شود و از طریق پیامهای ناهمگام (Asynchronous Messages) با رابط کاربری ارتباط برقرار کند. این رویکرد ساختاری، مشابه تغییری است که در تبدیل طراحیهای نامنظم به کدهای ساختاریافته در ابزار Figma مشاهده میکنیم تا خروجی نهایی قابلاستفادهتر باشد.
استراتژیهای فنی پیشنهادی عبارتند از:
- پیادهسازی Web Worker: ایجاد یک اسکریپت مجزا که مدل هوش مصنوعی را بارگذاری میکند. استفاده از
postMessageبرای ارسال دادههای ورودی به Worker و دریافت نتایج به صورت ناهمگام. در این حالت، وضعیت (State) در React تنها زمانی بهروز میشود که Worker پاسخ دهد تا رابط کاربری روان باقی بماند. - تکهبندی استنتاج (Inference Chunking): برای APIهایی که از این قابلیت پشتیبانی میکنند، استفاده از
requestIdleCallbackیا زمانبندی میکروتسکها (Microtasks) برای شکستن کارهای سنگین به دستههای کوچکتر. این کار به مرورگر اجازه میدهد بهروزرسانیهای UI و کارهای AI را به صورت متناوب انجام دهد و به رابط کاربری «فرصت نفس کشیدن» بدهد. - مدیریت چرخه حیات: پیادهسازی بارگذاری تنبل (Lazy Loading) برای وزنهای مدل تا از تأخیرهای سنگین در هنگام لود اولیه صفحه جلوگیری شود. علاوه بر این، نمونه مدل باید کش شود تا فراخوانیهای مکرر استنتاج، اپلیکیشن را مجبور به بارگذاری مجدد وزنها نکند.
تبادلهای UX و عملکرد ادراکشده
از منظر تجربه کاربری (UX)، این گزارش پیشنهاد میکند که از اسپینرهای ساده فراتر برویم. یک الگوی مقاومتر شامل چندین مکانیسم بازخورد ظریف است:
- UI خوشبینانه (Optimistic UI): نمایش نتایج اولیه یا جایگذارهای (Placeholders) سریع برای ایجاد حس پیشرفت آنی در کاربر.
- بازخورد پیشرونده: اگر استنتاج بیش از ۲۰۰ میلیثانیه طول کشید، یک نشانگر بارگذاری ظریف فعال شود.
- کنترل ورودی: غیرفعال کردن فیلدهای ورودی در طول استنتاج فعال تا از ارسال درخواستهای همزمان متعدد توسط کاربر جلوگیری شود.
- زمانبندی و لغو: ایجاد راهکاری برای کاربران تا بتوانند پردازشهای طولانیمدت را لغو کنند.
نویسنده به یک موفقیت خاص اشاره میکند: جایگزینی اسپینر استاندارد با یک لایه نیمهشفاف (Dimmed Overlay) و پیام «در حال تفکر...» که تنها در صورتی ظاهر میشود که زمان استنتاج از آستانه ۳۰۰ میلیثانیه عبور کند. این روش لرزشهای بصری (Visual Flicker) را در اجراهای سریع حذف کرده و در عین حال انتظارات را برای اجراهای کند مدیریت میکند.
عیبیابی تأخیر در AI
عیبیابی این گلوگاهها نیازمای یک جریان کاری خاص در Chrome DevTools است. نویسنده خاطرنشان میکند که استفاده از تب Performance برای شناسایی «وظایف طولانی» (Long Tasks) در نمودارهای Flame Chart، تنها راه قابلاعتماد برای یافتن دقیق این است که کدام فراخوانی model.predict باعث یخ زدن صفحه میشود. چنین تحلیلهایی برای شناسایی گلوگاههای پنهانی که باعث نشت زمان در گردشکارهای AI میشوند حیاتی است.
گامهای کلیدی عیبیابی شامل موارد زیر است:
- ضبط یک پروفایل (Profile) در طول استنتاج برای شناسایی مسدودیتهای رشته اصلی.
- استفاده از React DevTools برای تأیید اینکه آیا بهروزرسانیهای State یا رندرهها به تأخیر افتادهاند یا خیر.
- مانیتور کردن تب Network برای اطمینان از اینکه وزنهای مدل به طور مکرر دریافت نمیشوند.
در یک تست عملی، نویسنده دریافت که یک پیشبینی برای یک ورودی معمولی ۶۰۰ میلیثانیه زمان برد که چرخه رندر React را کاملاً مسدود کرد. برای رفع این مشکل، آنها از یک useRef برای Worker و یک هوک useEffect برای مدیریت چرخه حیات و خاتمه دادن به Worker استفاده کردند.
این تغییر رویکرد به این معناست که هوش مصنوعی در فرانتاند دیگر فقط درباره اندازه مدل نیست، بلکه درباره مدیریت رشتههاست. توسعهدهندگانی که رشته اصلی را نادیده میگیرند، در واقع عملکرد ادراکشده مدل خود را تخریب میکنند، فارغ از اینکه خود مدل چقدر بهینه شده باشد. هدف باید حرکت از ادغام ساده «نصب و اجرا» به سمت یک معماری ناهمگام اختصاصی باشد.
گام بعدی شما
- تمام فراخوانیهای
model.predictرا در پروژههای خود بررسی کنید و آنها را به یک Web Worker منتقل کنید. - از تب Performance در مرورگر کروم برای شناسایی Long Tasks بالای ۵۰ میلیثانیه استفاده کنید.
- سیستم بازخورد UI خود را از اسپینرهای دائمی به مدلهای شرطی (مثلاً نمایش بعد از ۳۰۰ میلیثانیه) تغییر دهید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای NPU در لپتاپهای جدید مراجعه کنید.




گفتگو