دیتاداگ سربار کلاسمچینگ جاوا رو ۳۰٪ کم کرد
خلاصهٔ کاملتر
زمان استارت برای همه مهمه؛ هم کاربری که منتظر پاسخه، هم توسعهدهندهای که داره تست میگیره، هم تیمی که حواسش به هزینهٔ ابره. تو جاوا، APM دیتاداگ با چسبوندن یه ایجنت به JVM کار میکنه که کلاسها رو موقع لود شدن تغییر میده تا قابلیت مشاهدهپذیری اضافه بشه. نویسنده میگه اینجا یه معاملهٔ همیشگی وجود داره: کم دستکاری کنی جزئیات مهم رو از دست میدی، زیاد دستکاری کنی استارت کند میشه.
یه اپلیکیشن معمولی جاوا دهها هزار کلاس داره و یه اپ سازمانی بزرگ ممکنه بیشتر از ۱۰۰ هزار کلاس لود کنه. چون بررسی ساختاری و سلسلهمراتبی نیاز به پارس کردن فایل کلاس داره و گرونه، اولین فیلتر همیشه مقایسهٔ اسم کلاس با یه لیست پیشوندهای بیاهمیته. همین باعث میشه کوچیکترین بهبود تو الگوریتم تطبیق پیشوند، اثر قابل اندازهگیری روی زمان استارت بذاره.
مشکل اینجاست که این تطبیق باید تو فاز premain انجام بشه — قبل از اجرای متد main برنامه. اون لحظه تقریباً هیچ کلاسی لود نشده، JIT سرده و بعضی کلاسهای JDK عوارض جانبی برگشتناپذیر دارن؛ مثلاً هر چیزی که java.util.logging رو صدا بزنه سینگلتون LogManager رو مقداردهی میکنه و اگر برنامه بخواد LogManager سفارشی خودش رو ست کنه، عملاً خراب میشه. تو جاوا ۸ اوضاع بدتره، چون JIT اصلاً تا بعد از premain روشن نمیشه.
راهحل تیم، ClassNameTrie بود: یه ترای پیشوندی که بهجای فایل جدا، بهشکل یه رشتهٔ ثابت داخل خود کلاس ذخیره میشه. هر کاراکتر جاوا ۲ بایته و ۶۵۵۳۶ مقدار ممکن داره، پس میشه هم اطلاعات کنترلی و هم محتوا رو تو یه رشته جا داد: تعداد شاخهها، کاراکترهای مرتبشدهٔ شاخه برای جستوجوی دودویی، مقدارها (برگ، جوانه، یا طول قطعهٔ درونخطی) و آفستهای پرش. مزیتش اینه که JVM خودش موقع لود کلاس رشته رو میاره و با یه دستور ldc در دسترسه — بدون I/O و بدون پارس.
برای سنجش، تیم بهجای بنچمارک معمولی با وارمآپ، از حالت SingleShotTime در JMH استفاده کرده تا شرایط استارت سرد رو شبیهسازی کنه و ۳۲ هزار اسم کلاس رایج رو تطبیق داده. نتیجه: ClassNameTrie رو جاوا ۸ نزدیک ۵ برابر سریعتر از روش کدمحور قبلی و حتی سریعتر از یه رادیکسترای کلاسیکه. تو یه اپ واقعی Spring Boot، فیلتر کردن کلاسهای بیاهمیت با اسم ۲۰ درصد از زمان استارت رو کم کرده، خود ClassNameTrie ۱ درصد دیگه، و یه ایندکس «تایپهای شناختهشده» ۳ درصد بیشتر — رویهم بیش از ۲۴ درصد.
نکات کلیدی:
- کلاسمچینگ اولین و گرونترین قدم ابزارگذاری APM جاواست و با فیلتر اسمی ارزون میشه
- ClassNameTrie یه ترای پیشوندیه که کامل داخل یه ثابت رشتهای JVM کد شده و با ldc لود میشه
- تو فاز premain نه JIT هست نه اجازهٔ لمس هر کلاس JDK، پس داده از کد ارزونتر تموم میشه
- رو جاوا ۸ نزدیک ۵ برابر سریعتر از روش کدمحور قبلی و سریعتر از رادیکسترای کلاسیک
- مجموع صرفهجویی تو یه اپ Spring Boot بیشتر از ۲۴ درصد زمان استارت بوده
- کدش تو کتابخانهٔ متنباز dd-instrument-java در دسترسه




