Hacker News

ما C++ تک رشته ای را با Rust چند رشته ای وصل کردیم

ما C++ تک رشته ای را با Rust چند رشته ای وصل کردیم این تجزیه و تحلیل جامع از رابط، بررسی دقیق اجزای اصلی و مفاهیم گسترده تر آن را ارائه می دهد. حوزه های کلیدی تمرکز محور بحث: هسته مرکزی ...

1 min read Via antithesis.com

Mewayz Team

Editorial Team

Hacker News
در اینجا پست وبلاگ سئو کامل است:

ما C++ Single-threaded را با Multi-threaded Rust وصل کردیم

رابط کد ++ تک رشته ای با Rust چند رشته ای نه تنها امکان پذیر است، بلکه یکی از کاربردی ترین راه ها برای مدرن کردن سیستم های قدیمی بدون بازنویسی کامل است. در Mewayz، ما دقیقاً با این چالش روبرو شدیم که سیستم عامل تجاری 207 ماژول خود را برای خدمت به 138000 کاربر افزایش دادیم و نتایج اساساً طرز فکر ما را در مورد قابلیت همکاری سیستم ها تغییر داد.

چرا C++ Single-threaded را با Multi-threaded Rust واسط می کنید؟

اکثر سیستم‌های تولیدی سال‌ها کد C++ آزمایش‌شده در نبرد را حمل می‌کنند. بازنویسی همه چیز در Rust روی کاغذ جذاب به نظر می رسد، اما ریسک عظیم و ماه ها زمان مهندسی را به همراه دارد. رویکرد عمل‌گرایانه، پذیرش تدریجی است - منطق C++ موجود را در هم می‌پیچانیم در حالی که بارهای کاری سنگین همزمان را به مدل مالکیت Rust بارگذاری می‌کنیم.

در مورد ما، ماژول‌های منطق کسب‌وکار اصلی سال‌ها به‌طور قابل‌اطمینانی در C++ تک رشته‌ای اجرا می‌شدند. آنها پردازش کارهای متوالی، تولید اسناد و محاسبات مالی را انجام می دادند. اما وقتی تعداد کاربران ما از 100 هزار گذشت، به پردازش موازی داده، مدیریت همزمان API و مدیریت ایمن حالت اشتراکی نیاز داشتیم. ویژگی‌های Send و Sync Rust به ما تضمین‌های همزمانی در زمان کامپایل می‌دهد که C++ به سادگی نمی‌تواند بدون ممیزی دستی گسترده ارائه دهد.

انگیزه اصلی کاهش ریسک است. آنچه را که کار می‌کند نگه می‌دارید، و چه مقیاس‌هایی را اضافه می‌کنید - بدون اینکه کل پایگاه کد خود را در انتقالی که ممکن است هرگز تمام نشود، قمار کنید.

مرز FFI در واقع چگونه کار می کند؟

رابط عملکرد خارجی (FFI) بین C++ و Rust از طریق امضاهای تابع سازگار با C عمل می کند. بلوک خارجی "C" Rust توابعی را که C++ می‌تواند مستقیماً فراخوانی کند و بالعکس را نشان می‌دهد. چالش حیاتی زمانی پدیدار می‌شود که زمان اجرا چند رشته‌ای Rust نیاز به فراخوانی کد تک رشته‌ای C++ به صورت ایمن داشته باشد.

ما این را با استفاده از معماری اختصاصی حل کردیم:

  • مجری C++ محدود به رشته: همه تماس‌های C++ از طریق یک رشته اختصاصی با استفاده از یک کانال ارسال پیام منتقل می‌شوند و این اطمینان را می‌دهد که هرگز تغییر ناپذیر تک رشته‌ای نقض نمی‌شود.
  • Rust async bridge layer: tasks Tokio کار را به مجری C++ ارسال می‌کند و از طریق کانال‌های oneshot نتایج انتظار را ارائه می‌کند و قسمت Rust را کاملاً ناهمزمان نگه می‌دارد.
  • مدیریت اشاره گر مات: اشیاء C++ در ساختارهای Rust پیچیده شده‌اند که Drop را برای پاکسازی قطعی پیاده‌سازی می‌کنند و از نشت حافظه در سراسر مرز زبان جلوگیری می‌کنند.
  • سریال سازی در مرز: ساختارهای داده پیچیده به FlatBuffers در لایه FFI سریال می شوند، از تطبیق طرح ساختار شکننده جلوگیری می کنند و امکان تکامل مستقل هر طرف را فراهم می کنند.
  • جداسازی هراس: Rust's catch_unwind هر نقطه ورودی FFI را می‌پوشاند به طوری که هراس هرگز از مرز زبان عبور نمی‌کند، که رفتاری نامشخص است.

این الگو به ما توان عملیاتی Rust چند رشته‌ای را با قابلیت اطمینان منطق C++ اثبات‌شده - بدون بازنویسی حتی یک خط از قوانین اصلی کسب‌وکار، داد.

بزرگترین دام هایی که باید از آنها اجتناب کنید چیست؟

خطرناک ترین اشتباه این است که فرض کنیم کد C++ امن است در حالی که اینطور نیست. وضعیت جهانی، متغیرهای استاتیک، و فراخوانی های کتابخانه بدون ورود مجدد باعث رقابت های داده ای می شوند که کامپایلر Rust نمی تواند آن را در سراسر مرز FFI تشخیص دهد. ضمانت‌های ایمنی Rust در بلوک ناامن متوقف می‌شوند - همه چیز در داخل مسئولیت شماست.

بینش کلیدی: Rust ایمنی حافظه را در کد خود تضمین می‌کند، اما لحظه‌ای که از مرز FFI در C++ عبور می‌کنید، هر مشکل ایمنی رشته‌ای را که C++ دارد به ارث می‌برید. معماری اطراف آن مرز مهمتر از کد دو طرف آن است.

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Start Free →

یک دام رایج دیگر مدیریت مادام العمر است. اشیاء C++ در بررسی قرض Rust شرکت نمی کنند. اگر Rust یک مرجع را رها کند در حالی که C++ همچنان نشانگر را نگه داشته است، باگ‌هایی بدون استفاده مواجه می‌شوید که تشخیص آنها بسیار دشوار است. ما با اعمال معنایی دقیق مالکیت به این موضوع پرداختیم: اشیاء C++ همیشه دقیقاً متعلق به یک Rust wrapper هستند و دسترسی مشترک از طریق شمارش مرجع مبتنی بر Arc در سمت Rust انجام می‌شود.

از نظر عملکرد، تماس‌های بیش از حد FFI باعث ایجاد هزینه‌های اضافی از تغییر زمینه و سریال‌سازی می‌شود. ما هر جا که ممکن است عملیات دسته‌بندی می‌کنیم، به جای برقراری تماس‌های بین‌زبانی فردی، یک صف از موارد کاری را به مجری C++ ارسال می‌کنیم.

این رویکرد در تولید چگونه عمل کرد؟

پس از استقرار معماری ترکیبی در سرتاسر پلت فرم خود، پیشرفت‌های بتن را اندازه‌گیری کردیم. توان عملیاتی درخواست برای ماژول هایی که قبلاً در پردازش متوالی C++ در گلوگاه قرار داشتند، 3.4 برابر افزایش یافت. تأخیر Tail (p99) تا 61 درصد کاهش یافت زیرا زمان اجرا ناهمگام Rust می‌توانست درخواست‌های مستقل را همزمان پردازش کند در حالی که C++ وظایف محاسباتی سنگین را در رشته اختصاصی خود انجام می‌داد.

مهمتر از آن، ما در شش ماه اول تولید هیچ اشکال مرتبط با همزمانی نداشتیم. الگوی thread-confinement از نظر ساختاری فراخوانی کد C++ از چندین رشته را غیرممکن می‌کرد، در حالی که سیستم نوع Rust از مسابقه داده در سمت مرز جلوگیری می‌کرد. این یک پیشرفت قابل توجه نسبت به رویکرد قبلی ما در تلاش برای افزودن threading به C++ با mutexes بود، که در یک سه ماهه سه رویداد مسابقه را ایجاد کرده بود.

تیم مهندسی همچنین چرخه‌های تکرار سریع‌تری را گزارش کردند. ویژگی‌های جدید را می‌توان در Rust با پشتیبانی کامل همزمان ایجاد کرد، در حالی که ماژول‌های C++ موجود بدون تغییر به کار خود ادامه دادند. این استراتژی افزایشی به این معنی بود که ما هرگز یک مهاجرت پرخطر "بیگ بنگ" نداشتیم — فقط بهبود ثابت و قابل اندازه گیری.

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

آیا Rust می‌تواند کتابخانه‌های C++ تک رشته‌ای را بدون تغییر فراخوانی کند؟

بله، اما باید مطمئن شوید که همه تماس‌ها به آن کتابخانه از یک رشته انجام می‌شود. الگوی استاندارد ایجاد یک رشته مجری اختصاصی است که تمام تماس‌های C++ را از طریق یک کانال سریال‌سازی می‌کند. وظایف همگام Rust بدون مسدود کردن زمان اجرا چند رشته ای درخواست ها را ارسال می کنند و منتظر پاسخ هستند. خود کد C++ به هیچ تغییری نیاز ندارد - محدودیت ایمنی به طور کامل در سمت Rust اعمال می‌شود.

آیا سربار FFI به اندازه کافی مهم است که بر عملکرد برنامه تأثیر بگذارد؟

تماس‌های FFI انفرادی حداقل سربار دارند — معمولاً کمتر از 10 نانوثانیه برای یک تماس تابع ساده. با این حال، در صورت برقراری هزاران تماس دقیق، سریال سازی ساختارهای داده پیچیده و همگام سازی رشته ها در مرز افزایش می یابد. عملیات دسته‌ای و استفاده از قالب‌های سریال‌سازی بدون کپی مانند FlatBuffers یا Cap'n Proto، هزینه‌های سربار را حتی در مقیاس ناچیز نگه می‌دارد.

آیا باید به جای رابط، پایگاه کد C++ خود را در Rust بازنویسی کنیم؟

برای اکثر تیم‌ها، رابط افزایشی مسیر امن‌تر و سریع‌تر است. بازنویسی کامل، ماه‌ها ریسک مهندسی را بدون هیچ ارزشی برای کاربر تا زمان تکمیل معرفی می‌کند. رابط به شما امکان می‌دهد فوراً بهبودها را ارسال کنید، رویکرد Rust را در تولید تأیید کنید، و ماژول‌ها را یکی یکی بر اساس جایی که همزمانی بیشترین تأثیر را دارد، منتقل کنید. فقط ماژول هایی را بازنویسی کنید که هزینه حفظ مرز FFI از هزینه بازنویسی بیشتر باشد.


در Mewayz، ما زیرساخت‌هایی را ایجاد می‌کنیم که مقیاس‌پذیر باشد - هم از نظر فنی و هم از نظر عملیاتی. سیستم‌عامل تجاری ۲۰۷ ​​ماژول ما به ۱۳۸۰۰۰ تیم کمک می‌کند گردش‌های کاری هوشمندانه‌تری را با شروع از ۱۹ دلار در ماه انجام دهند. فرقی نمی‌کند پروژه‌ها را مدیریت می‌کنید، عملیات‌ها را خودکار می‌کنید یا کسب و کارتان را مقیاس‌بندی می‌کنید، Mewayz با روش کار شما سازگار می‌شود. دوره آزمایشی رایگان خود را در app.mewayz.com شروع کنید و ببینید که یک سیستم‌عامل تجاری مدرن چه کاری می‌تواند برای تیم شما انجام دهد.

Try Mewayz Free

All-in-one platform for CRM, invoicing, projects, HR & more. No credit card required.

Related Guide

HR Management Guide →

Manage your team effectively: employee profiles, leave management, payroll, and performance reviews.

Start managing your business smarter today

Join 30,000+ businesses. Free forever plan · No credit card required.

Ready to put this into practice?

Join 30,000+ businesses using Mewayz. Free forever plan — no credit card required.

Start Free Trial →

Ready to take action?

Start your free Mewayz trial today

All-in-one business platform. No credit card required.

Start Free →

14-day free trial · No credit card · Cancel anytime