تصور کنید یک اسکن ۲۰ میلیون خطی که ۱۸۱ ثانیه زمان میبرد، ناگهان در ۲۵ ثانیه به پایان برسد. این جهش ۷ برابری در سرعت، نتیجهی استفادهی خالق basemind از Claude Code در ۸ ژوئیه ۲۰۲۶ بود تا بهجای حدس زدن تغییرات کد، مستقیماً دینامیکهای زنده سیستم را اندازهگیری کند.
همانطور که در تحلیل قبلی ما دربارهی پیشتازی Claude Fable 5 در محکهای صنعتی اشاره کردیم، این مورد نشان میدهد که ابزارهای کدنویسی عاملمحور (Agentic) — شبیه دستیاری که نهتنها متن مینویسد، بلکه میتواند ابزارهای سیستم را اجرا کند و نتایج را تحلیل کند — در حال گذار از تولید تکههای کد ساده به عیبیابی سیستمهای پیچیده هستند. برای اکثر برنامهنویسان، شکار نشت عملکرد شبیه تعقیب یک روح در ماشین است؛ شما یک خط کد را تغییر میدهید، سیستم را ریاستارت میکنید و امیدوارید عدد نهایی پایین بیاید.
ابزار و محیط آزمایش
برای درک مقیاس این عملیات، ابتدا باید basemind را بشناسیم. این ابزار هوش کد (Code Intelligence) با زبان Rust نوشته شده و از یک نقشهی کد و اسکنری بهره میبرد که از tree-sitter در بیش از ۳۰۰ زبان برنامهنویسی استفاده میکند. معماری آن بر یک ذخیرهساز blob با آدرسدهی محتوایی (content-addressed) و یک ایندکس معکوس متکی است که توسط Fjall پشتیبانی میشود.
به نقل از مستندات این پروژه، توسعهدهنده برای سختترین حالت ممکن، ابزار را روی یک مخزن عظیم (Monorepo) قرار داد که بهطور خاص برای «شکنجه دادن» سیستم طراحی شده بود: مخزنی حاوی ۲۰ میلیون خط کد و ۲۰۰ هزار کامیت. این محیط فشار لازم برای آشکار کردن گلوگاههای عمیق معماری را فراهم کرد.
وقتی نشانه، با باگ متفاوت است
در این جلسه با Claude Code، روند سنتی عیبیابی کاملاً تغییر کرد. گزارش اولیه نشان میداد حافظه پنهان (Cache) از ۱.۸ گیگابایت به ۴ گیگابایت رسیده و CPU برای مدتی طولانی در حالت اشباع (Pinned) قرار گرفته است. بهجای باز کردن کد اسکنر، توسعهدهنده از هوش مصنوعی خواست تا سیستم زنده را با ابزارهایی مثل ps و lsof رصد کند.
این بررسی فاش کرد که یک پردازش با حدود ۷۰٪ مصرف CPU، ایندکس را باز نگه داشته است. نکته کلیدی اینجا بود که این پردازش مربوط به serve بود، نه scan. در این لحظه، مسیر تحقیقات از دیباگر به git تغییر کرد. با استفاده از git log روی watcher و دستور git merge-base --is-ancestor برای بررسی تاریخ کامیتها، آنها کامیتی با عنوان "fix: stop watcher CPU runaway" پیدا کردند که تاریخ آن چهار روز بعد از انتشار نسخه باینری در حال اجرا بود.
باگ — که یک حلقه بینهایت بود و باعث میشد watcher نوشتههای خودش را دوباره اسکن کند — پیش از این رفع شده بود. این «نشت» در واقع صرفاً یک پردازش قدیمی (stale process) بود که از جلسات قبلی ویرایشگر باقی مانده بود. این تجربه دو درس حیاتی داد: اول، بهجای تکیه بر واسطهها (چون Homebrew، متغیر PATH و پلاگین ویرایشگر همگی نسخههای متفاوتی را گزارش میکردند)، همیشه خودِ آرتیفکت در حال اجرا را تأیید کنید و دوم، همیشه بپرسید «آیا این یک باگ زنده است یا یک بیلد قدیمی؟»
اندازهگیری همگرایی
پس از حذف پردازش مزاحم، اسکن جدید ۵ هسته CPU را با ۴۸۸٪ درگیر کرد. در یک نگاه اول، این وضعیت از یک حلقه بینهایت غیرقابل تشخیص است. برای تشخیص تفاوت بین یک حلقه و یک اسکن سالم، توسعهدهنده از Claude Code خواست تا مانیتورهای شل (Shell) در پسزمینه بنویسد که هر ۳۰ ثانیه سه سیگنال را نمونهبرداری کنند: درصد CPU، اندازه حافظه پنهان و تعداد blobها.
طبق گزارش توسعهدهنده، تحلیل به این صورت بود:
- تشخیص: نشت حافظه مدام تخصیص میدهد، حلقه مدام مینویسد، اما اسکن همگرا (Converge) میشود.
- مشاهده: مصرف دیسک بالا رفت و سپس به حالت پلاتو (ثابت) رسید؛ نوشتن blobها جهشی داشت و سپس متوقف شد؛ CPU در نهایت به یک هسته کاهش یافت.
- نتیجه: مشتق دادهها ثابت کرد سیستم در حال بازسازی یکباره است، نه نشت حافظه.
برای اینکه توسعهدهنده مجبور نباشد مدام پردازش را زیر نظر بگیرد، مانیتورها بهگونهای برنامهریزی شدند که فقط در زمان تغییر وضعیت (State Transition) چاپ کنند؛ مثلاً عباراتی مثل "SCAN COMPLETE + IDLE" یا "۰٪ CPU و عدم رشد دیسک برای ۴ دقیقه".
جداسازی توقفهای شبکه
مشکل بعدی، توقف کامل سیستم (Total System Hang) در تستهای multi-worktree بود. اسکنها در ۰٪ CPU قفل میشدند و اجرای lsof روی خودِ پردازش متوقفشده، دو دقیقه طول میکشید. یک lsof متوقفشده معمولاً نشانه یک سوکت مسدود شده است.
آخرین خط لاگ این بود: Registering VLM OCR backend. بررسیها نشان داد که لایه OCR از طریق وابستگی hf_hub (نسخههای ۰.۴ و ۰.۵) یک فراخوانی شبکه با استفاده از یک ایجنت ureq انجام میداد که هیچ timeout یا مهلتی نداشت. وقتی یک فایروال بسته (drop) میکرد، اتصال برای همیشه مسدود میشد.
برای جداسازی این مشکل، توسعهدهنده یک متغیر را تغییر داد: او basemind را با ویژگیهای پیشفرض بیلد کرد و قابلیت اختیاری (opt-in) OCR در cargo را غیرفعال نمود. این کار باینریای ایجاد کرد که نمیتوانست آن فراخوانی را انجام دهد و به این ترتیب اجازه داد منطق داخلی اسکنر بهطور مجزا از توقفهای شبکه مطالعه شود.
بهینهسازی مکانیزم
با رفع توقفها، تمرکز روی زمان ۱۸۱ ثانیهای اسکن رفت. توسعهدهنده یک خط پایه (Baseline) گرفت: اسکن یک worktree تازه، تمام ۶۷,۷۰۰ فایل را دوباره تجزیه (Parse) میکرد — حتی با وجود اینکه blobهای آنها از قبل در ذخیرهساز مشترک موجود بود — و ایندکس تاریخچه git را برای هر worktree در حدود ۱۶۰ ثانیه بازسازی میکرد.
توسعهدهنده با خواندن کد برای تأیید مکانیزم، متوجه شد که مسیرهای سریع «فایلهای تغییرنیافته» (unchanged file fast paths) بر اساس ایندکس هر worktree عمل میکنند، که در یک worktree تازه، این ایندکس خالی بود. علاوه بر این، ایندکس تاریخچه git بهجای استفاده از پوشه .git مشترک، در دایرکتوری کشِ خودِ worktree باز میشد.
پس از نوشتن تستهای رگرسیون (که ابتدا باید شکست میخوردند)، اصلاحات اعمال شد و منجر به تغییرات دراماتیک در معیارها گشت:
- زمان اسکن: از ۱۸۱ ثانیه به ۲۵ ثانیه رسید (تقریباً ۷ برابر سریعتر).
- حافظه: اوج مصرف RSS تقریباً نصف شد.
- کارایی: تمام ۶۷,۷۰۰ فایل با موفقیت بازاستفاده شدند.
اصلاح در سطح وابستگیها
توقف شبکه در وابستگیها همچنان نیاز به اصلاح داشت. توسعهدهنده مخزن hf_hub را فورک کرد و از یک زیر-عامل (Subagent) با یک مشخصات (Spec) دقیق خواست تا تمام نقاط فراخوانی دانلود را در دو crate شناسایی و نقشهبرداری کند. آنها یک watchdog پیاده کردند که عملیات مسدودکننده fetch را در یک رشته (Thread) جداگانه اجرا میکند و در صورت رسیدن به یک مهلت قابل تنظیم (tunable deadline)، خطا میدهد. این باعث شد سیستم بهجای توقف کامل، با نادیده گرفتن مدل، بهطور graceful تخریب شود.
این زیر-عامل حتی یک فرض انسانی را اصلاح کرد؛ جایی که تصور میشد یک تایپ خاص قابلیت Clone ندارد. این کار از طریق diffها و اجرای مجدد (و نه صرفاً خلاصه متنی) تأیید شد و بهعنوان یک PR و گزارش باگ به پروژه اصلی ارسال گردید.
هرس کردن قابلیتها
در نهایت، مانیتورینگ نشان داد که مرحله بردار معنایی (Embedding) روی یک مدل عمومی گیر کرده است و به دلیل وجود یک قفل قدیمی (stale lock) در دایرکتوری خالی مدل، یک هسته CPU را درگیر کرده است. توسعهدهنده این سؤال را مطرح کرد که آیا اصلاً به بردار معنایی برای کد نیاز است؟
ردیابی مکانیزم نشان داد که یک مدل انگلیسی-عمومی، کد را بهطور ضعیفی بردارسازی میکند، در حالی که basemind پیش از این یک ایندکس BM25 روی همان متنها (نمادها، امضاها، مستندات و بدنه کد) ساخته بود. هزینه این قابلیت، دانلود ۱۰۰ مگابایت مدل و اشغال گیگابایتها حافظه برای بردی بود که از قبل توسط مسیر جستوجوی کلیدواژهای پوشش داده شده بود. حکم نهایی این بود: بردار معنایی برای کد بهصورت پیشفرض خاموش شد و فقط برای مستندات و تصاویر باقی ماند. قابلیتی که خاموش باشد، نمیتواند باعث توقف، نشت یا اشغال CPU شود.
این گردش کار، عاملهای هوش مصنوعی را به شریکی در چرخه «اندازهگیری-جداسازی-اصلاح» تبدیل میکند. با سپردن کارهای مکانیکی مثل نقشهبرداری از نقاط فراخوانی و نوشتن مانیتورها به AI، انسان روی مکانیزم و تأیید نهایی تمرکز میکند. پروژه basemind در آدرس github.com/Goldziher/basemind در دسترس است.
گام بعدی شما
- اگر با گلوگاههای عملکردی در پروژههای بزرگ مواجهید، بهجای تغییر کد، ابتدا مانیتورهای زنده برای CPU و I/O بنویسید.
- در استفاده از ابزارهای عاملمحور، از آنها بخواهید برای هر فرضیه، یک تست رگرسیون بنویسند تا از بازگشت باگ جلوگیری شود.
- وابستگیهای شبکه را همیشه با timeoutهای سخت تعریف کنید تا از توقف کامل (Hang) سیستم جلوگیری شود.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو