برچسب: اندروید

  • پینترست چگونه زمان CI اندروید را بیش از ۳۶٪ کاهش داد؟

    پینترست چگونه زمان CI اندروید را بیش از ۳۶٪ کاهش داد؟

    پینترست به‌تازگی یک مطالعه موردی فنی (Technical Case Study) منتشر کرده است. این گزارش نشان می‌دهد تیم مهندسی شرکت چگونه با بازطراحی زیرساخت تست، زمان اجرای CI اندروید را بیش از ۳۶ درصد کاهش داد. این بهبود با پیاده‌سازی یک استراتژی شاردینگ آگاه از زمان اجرا (Runtime-aware Test Sharding) به دست آمد.

    پیش از این تغییرات، پایپ‌لاین CI اندروید پینترست عملکرد کند و غیرقابل‌پیش‌بینی داشت. توزیع نامناسب تست‌ها باعث می‌شد زمان بیلد به‌شدت افزایش پیدا کند. تیم تست‌ها را در پلتفرم‌های شخص ثالث فقط بر اساس نام پکیج‌ها شارد می‌کرد. در نتیجه، کندترین شارد کل فرایند CI را متوقف می‌کرد.

    مشکل کجا بود؟

    در معماری قبلی، پینترست از Firebase Test Lab (FTL) استفاده می‌کرد. این سرویس تست‌ها را بر اساس گروه‌بندی پکیج‌ها توزیع می‌کرد. این روش یک ضعف جدی داشت. برخی تست‌ها زمان اجرای بسیار طولانی‌تری نسبت به سایرین داشتند. این موضوع بار کاری شاردها را نامتوازن می‌کرد. در نهایت، کندترین شارد زمان کل CI را تعیین می‌کرد.

    علاوه بر این، تیم با چالش‌های دیگری هم مواجه بود. flakiness تست‌ها افزایش یافته بود. راه‌اندازی محیط تست overhead قابل‌توجهی داشت. هر اجرای CI چند دقیقه زمان سربار اضافه می‌کرد.

    پس از بررسی گزینه‌های موجود، تیم مهندسی به یک نتیجه روشن رسید. هیچ‌یک از راهکارهای شخص ثالث نیازهای پینترست را به‌طور کامل پوشش نمی‌دادند. این ابزارها پشتیبانی بومی مناسبی از emulator نداشتند. همچنین امکان کنترل دقیق orchestration و زمان‌بندی را فراهم نمی‌کردند.

    تولد PinTestLab؛ زیرساخت تست داخلی پینترست

    این تحلیل به توسعه یک پلتفرم داخلی به نام PinTestLab منجر شد. این زیرساخت emulatorهای اندروید را روی EC2 اجرا می‌کند. تیم با این سیستم کنترل کامل محیط اجرا، زمان‌بندی و orchestration را در اختیار دارد. PinTestLab وابستگی به سرویس‌های خارجی را نیز به‌طور قابل‌توجهی کاهش می‌دهد.

    نوآوری اصلی: شاردینگ مبتنی بر زمان اجرای واقعی

    هسته این تحول، یک الگوریتم شاردینگ آگاه از زمان اجرا است. این الگوریتم برخلاف روش‌های رایج مانند round-robin یا تقسیم ساده تست‌ها عمل می‌کند. سیستم از داده‌های تاریخی اجرای تست‌ها استفاده می‌کند. مدت‌زمان مورد انتظار هر تست از سیستم مدیریت تست پینترست (Metro) خوانده می‌شود.

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

    نتیجه این تغییرات چشمگیر بود. اختلاف بین سریع‌ترین و کندترین شارد از چند صد ثانیه به چند ده ثانیه کاهش یافت. زمان اجرای کندترین شارد حدود ۵۵ درصد کمتر شد. توسعه‌دهندگان نیز بازخورد CI را در هر بیلد حدود ۹ دقیقه سریع‌تر دریافت کردند.

    چرا داده‌های تاریخی نقش کلیدی دارند؟

    برخلاف توزیع مساوی تست‌ها بر اساس تعداد، این رویکرد از داده‌های واقعی استفاده می‌کند. سیستم emulatorها را همیشه مشغول نگه می‌دارد. tail latency کاهش می‌یابد و رفتار CI اندروید قابل پیش‌بینی‌تر می‌شود.

    در پیاده‌سازی، تیم از الگوریتمی ساده اما مؤثر استفاده کرد. این الگوریتم شامل مرتب‌سازی سبک، تخصیص greedy و استفاده از ساختار داده min-heap است. این ترکیب، تعادل خوبی میان کارایی عملی و سادگی محاسباتی ایجاد می‌کند.

    پایداری عملیاتی؛ اولویتی جدی

    منطق شاردینگ درون Buildkite اجرا می‌شود. اگر داده‌های Metro در دسترس نباشند، سیستم به‌صورت خودکار به round-robin fallback می‌کند. این تصمیم طراحی باعث شده CI حتی در شرایط اختلال زیرساختی هم پایدار باقی بماند.

    در آینده، تیم پینترست روی on-demand sharding، استفاده از message queue و اجرای granularتر تست‌ها تمرکز خواهد کرد. با این حال، راهکار فعلی بهترین نسبت کارایی به پیچیدگی را ارائه می‌دهد.

    این فقط پینترست نیست؛ یک روند عمومی در CI مدرن

    پینترست تنها شرکتی نیست که این مسیر را انتخاب کرده است. Dropbox با اجرای فقط تست‌های مرتبط با تغییرات، زمان CI اندروید را از ۷۵ دقیقه به ۲۵ دقیقه کاهش داد. Shopify با شاردینگ مبتنی بر داده‌های تاریخی، زمان CI را از ۴۵ دقیقه به ۱۱ دقیقه رساند. این شرکت اختلاف زمان شاردها را به کمتر از ۵ درصد کاهش داد.

    Square در ابزار داخلی Kochiku روی شاردینگ گسترده و زمان‌بندی هوشمند در مقیاس صدها شارد تمرکز دارد. پلتفرم‌هایی مانند Bitrise نیز با parallel execution آماده، کاهش زمان تست تا ۵۰ درصد را گزارش می‌کنند. Slack هم با حذف اجرای غیرضروری و reuse assetها، سرعت CI اندروید را تا ۵۰ درصد افزایش داده است.

    جمع‌بندی

    مطالعه موردی پینترست یک پیام روشن دارد. استفاده درست از داده‌های تاریخی می‌تواند CI اندروید را متحول کند. ترکیب داده‌های واقعی اجرا، حداکثرسازی parallelism و حذف کارهای غیرضروری، امروز به یک best practice در تیم‌های مهندسی پیشرو تبدیل شده است.

    راهکاری که پینترست پیاده‌سازی کرده، یک مدل عملی و قابل الگوبرداری است. این رویکرد به‌ویژه برای تیم‌هایی مفید است که با رشد تست‌ها از افزایش زمان CI اندروید رنج می‌برند؛ مشکلی رایج در توسعه نرم‌افزار مدرن.

    اگر به دنیای CI/CD علاقه دارید، می‌توانید مطالب این دسته‌بندی را در کدرزنیوز دنبال کنید.

  • اپل پیش‌نمایش SDK برای ساخت اپلیکیشن‌های اندروید با Swift را ارائه کرد

    اپل پیش‌نمایش SDK برای ساخت اپلیکیشن‌های اندروید با Swift را ارائه کرد

    اپل به تازگی Swift SDK برای اندروید را به صورت نسخه nightly build منتشر کرده است. هدف این SDK کمک به توسعه‌دهندگان برای انتقال بسته‌های Swift به اندروید است تا بتوانند به راحتی کدهای خود را بین پلتفرم‌ها به اشتراک بگذارند. هرچند Swift SDK هنوز در مرحله پیش‌نمایش است، بیش از ۲۵٪ از بسته‌های موجود در Swift Package Index هم‌اکنون قابلیت کامپایل برای اندروید را دارند.

    ساختار اصلی Swift SDK

    در هسته خود، Swift SDK برای اندروید شامل یک toolchain سفارشی Swift برای پلتفرم اندروید است؛ یعنی کامپایلر و پیاده‌سازی کتابخانه استاندارد Swift که روی اندروید اجرا می‌شود، به همراه مجموعه‌ای از bindings که دسترسی به APIهای اندروید از Swift را فراهم می‌کنند. این toolchain از پروژه swift-java-project برای تعامل بین Java و Swift استفاده می‌کند و می‌تواند shared objects بسازد که داخل فایل apk لینک شده و از طریق JNI قابل دسترسی باشند.

    پشتیبانی از رابط‌های کاربری (UI)

    Swift SDK برای اندروید رویکرد غیرجانبدارانه‌ای نسبت به UI دارد. به جای وابستگی به یک فریم‌ورک خاص، تیم توسعه‌دهنده از فریم‌ورک‌های موجود پشتیبانی می‌کند، از جمله:

    • ابزارهای بومی اندروید مانند Jetpack Compose و سیستم قدیمی XML-based
    • موتور UI فلاتر (Flutter)
    • راه‌حل‌های پل‌زنی شخص ثالث مانند Skip

    یک رویکرد احتمالی دیگر، که به طور صریح توسط تیم Swift Android اعلام نشده، این است که UI با استفاده از Swift و موتورهای رندرینگ مانند OpenGL یا Vulkan ساخته شود و سپس با NativeActivity در اپلیکیشن اندروید ادغام شود.

    به ویژه، فریم‌ورک Skip SwiftUI را برای اندروید بازپیاده‌سازی کرده و آن را به Jetpack Compose متصل می‌کند. این روش به توسعه‌دهندگان iOS اجازه می‌دهد هم منطق تجاری و هم UI اپلیکیشن خود را در همان کد بیس بنویسند، با کمترین تلاش اضافی.

    علاوه بر این، پروژه متن‌باز SwiftCrossUI نیز API مشابه SwiftUI ارائه می‌دهد و از macOS، لینوکس، ویندوز و به صورت محدود از اندروید پشتیبانی می‌کند.

    چالش‌های استفاده از Swift برای اپلیکیشن‌های چندپلتفرمی

    اگرچه ایده استفاده از Swift برای iOS و اندروید جذاب به نظر می‌رسد، ایجاد اپلیکیشن‌های چندپلتفرمی با کیفیت، فقط به ابزار و کتابخانه‌های بومی محدود نمی‌شود. کاربری و تجربه توسعه‌دهنده (Developer UX) از جمله چالش‌هاست، زیرا:

    • توسعه‌دهندگان iOS ممکن است دیباگ کردن روی اندروید را دشوار بیابند
    • ناسازگاری مدل‌ها بین Swift و Kotlin رخ می‌دهد (مثلاً Exception کاتلین قابل دریافت از Swift نیستند)
    • حتی Kotlin Multiplatform هم با Kotlin برای اندروید برابر نیست و عملاً یک زبان سوم معرفی می‌شود

    یش‌زمینه و گزینه‌های دیگر

    این SDK تقریباً شش ماه پس از اعلام ایجاد گروه کاری اندروید در پروژه Swift توسط اپل عرضه شد. هدف این گروه اطمینان از این بود که Swift بدون نیاز به فورک‌های غیررسمی روی اندروید کامپایل شود و کتابخانه‌های استاندارد Swift برای سازگاری بهتر با APIهای اندروید بهبود یابند.

    پیش از این، توسعه‌دهندگان می‌توانستند از راه‌حل‌های شخص ثالث مانند Scade.io برای کامپایل کد Swift روی اندروید استفاده کنند. Scade مبتنی بر Swift4j است و بیشتر روی منطق برنامه‌های غیر UI تمرکز دارد.

    برای توسعه‌دهندگان اندروید که قصد دارند اپلیکیشن خود را به iOS منتقل کنند، گزینه‌ای پیشرفته‌تر، استفاده از Kotlin Multiplatform همراه با Jetpack Compose Multiplatform است.