Hacker News

Liitimme yksisäikeisen C++:n monisäikeisen Rustin kanssa

Liitimme yksisäikeisen C++:n monisäikeisen Rustin kanssa Tämä kattava rajapintojen analyysi tarjoaa yksityiskohtaisen tarkastelun sen ydinkomponenteista ja laajemmista vaikutuksista. Keskeiset painopistealueet Keskustelu keskittyy: Ydinkone...

7 min read Via antithesis.com

Mewayz Team

Editorial Team

Hacker News
Tässä on täydellinen SEO-blogiviesti:

Liitämme yksisäikeisen C++:n monisäikeiseen ruosteeseen

Yksisäikeisen C++-koodin liittäminen monisäikeiseen Rustiin ei ole vain mahdollista – se on yksi käytännöllisimmistä tavoista modernisoida vanhoja järjestelmiä ilman täydellistä uudelleenkirjoitusta. Vastasimme Mewayzissä juuri tähän haasteeseen skaalattaessamme 207 moduulin yrityskäyttöjärjestelmää palvelemaan 138 000 käyttäjää, ja tulokset muuttivat perusteellisesti ajatteluamme järjestelmien yhteentoimivuudesta.

Miksi yhdistäisit yksisäikeisen C++:n monisäikeiseen ruosteeseen?

Useimmissa tuotantojärjestelmissä on vuosien taistelutestattua C++-koodia. Kaiken kirjoittaminen uudelleen Rustissa kuulostaa houkuttelevalta paperilla, mutta se tuo mukanaan valtavan riskin ja kuukausien suunnitteluajan. Pragmaattinen lähestymistapa on asteittainen käyttöönotto – olemassa olevan C++-logiikan käämitys ja samanaikaisuuden raskas työtaakka siirretään Rustin omistusmalliin.

Meidän tapauksessamme ydinliiketoiminnan logiikkamoduulit olivat toimineet luotettavasti yksisäikeisessä C++:ssa vuosia. He hoitivat peräkkäisten tehtävien käsittelyn, asiakirjojen luomisen ja talouslaskelmat. Mutta kun käyttäjäkuntamme kasvoi yli 100 000, tarvitsimme rinnakkaista tietojenkäsittelyä, samanaikaista API-käsittelyä ja turvallista jaetun tilan hallintaa. Rustin Lähetä- ja Sync-ominaisuudet antoivat meille käännösajan samanaikaisuuden takuut, joita C++ ei yksinkertaisesti pystyisi tarjoamaan ilman laajaa manuaalista tarkastusta.

Tärkein motivaatio on riskin vähentäminen. Säilytät sen, mikä toimii, ja lisäät mitkä mittakaavat – ilman, että pelaat koko koodikantasi siirtoon, joka ei ehkä koskaan lopu.

Kuinka FFI-raja itse asiassa toimii?

C++:n ja Rustin välinen Foreign Function Interface (FFI) toimii C-yhteensopivien funktioiden allekirjoitusten kautta. Rustin ulkoiset "C" -lohkot paljastavat toimintoja, joita C++ voi kutsua suoraan ja päinvastoin. Kriittinen haaste ilmenee, kun Rustin monisäikeisen ajonaikaisen on kutsuttava yksisäikeinen C++-koodi turvallisesti.

Ratkaisimme tämän käyttämällä erityistä arkkitehtuuria:

  • Säikeinen C++-suoritin: Kaikki C++-kutsut ohjataan yhden erillisen säikeen kautta viestinvälityskanavan kautta, mikä varmistaa, että yksisäikeistä invarianttia ei koskaan rikota.
  • Rust-asynkroninen siltakerros: Tokio-tehtävät lähettävät työn C++-suoritukseen ja odottavat tuloksia oneshot-kanavien kautta, jolloin ruostepuoli pysyy täysin asynkronisena.
  • Osoittimien läpinäkymätön hallinta: C++-objektit on kääritty Rust-rakenteisiin, jotka toteuttavat Drop-toiminnon determinististä puhdistusta varten, mikä estää muistivuodot kielirajojen yli.
  • Sarjoittaminen rajalla: Monimutkaiset tietorakenteet sarjoidaan FlatBuffereihin FFI-kerroksessa, jolloin vältetään hauraat rakenteiden asettelun yhteensovitukset ja mahdollistetaan kummankin puolen riippumaton kehitys.
  • Paniikkieristys: Rustin catch_unwind käärii jokaisen FFI-sisääntulopisteen, jotta paniikki ei koskaan ylitä kielirajoja, mikä olisi määrittelemätöntä toimintaa.

Tämä malli antoi meille monisäikeisen Rustin suorituskyvyn todistetun C++-logiikan luotettavuudella – kirjoittamatta uudelleen riviäkään alkuperäisiä liiketoimintasääntöjä.

Mitkä ovat suurimmat sudenkuopat, jotka on vältettävä?

Vaarallisin virhe on olettaa, että C++-koodi on säikeen turvallinen, vaikka se ei ole sitä. Globaali tila, staattiset muuttujat ja ei-palaavat kirjastokutsut aiheuttavat datakilpailuja, joita Rustin kääntäjä ei pysty havaitsemaan FFI-rajojen yli. Rustin turvallisuustakuut pysähtyvät turvattomaan-lohkoon – kaikki sisällä on sinun vastuullasi.

Tärkein näkemys: Rust takaa muistin turvallisuuden omassa koodissaan, mutta kun ylität FFI-rajan C++:aan, perit kaikki C++:n säikeiden turvallisuusongelmat. Arkkitehtuuri tuon rajan ympärillä on tärkeämpää kuin sen kummallakin puolella oleva koodi.

💡 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 →

Toinen yleinen sudenkuoppa on elinikäinen hallinta. C++-objektit eivät osallistu Rustin lainatarkistuksiin. Jos Rust pudottaa viitteen, kun C++:ssa on edelleen osoitin, saat käyttö-afree-virheitä, joita on raa'asti vaikea diagnosoida. Ratkaisimme tämän ottamalla käyttöön tiukan omistajuuden semantiikan: C++-objektit omistaa aina täsmälleen yksi Rust-kääre, ja jaettu käyttö tapahtuu ruosteen puolella kaaripohjaisen viitelaskennan kautta.

Suorituskyvyn kannalta ylimääräiset FFI-kutsut aiheuttavat kontekstin vaihtamisesta ja sarjoittamisesta aiheutuvia ylimääräisiä kustannuksia. Eräoperaatioita aina kun mahdollista, lähetämme jonon työkohteita C++-suorittimelle sen sijaan, että tekisimme yksittäisiä kielien välisiä kutsuja.

Kuinka tämä lähestymistapa toimi tuotannossa?

Kun hybridiarkkitehtuuri oli otettu käyttöön alustallamme, mittasimme konkreettisia parannuksia. Pyyntöjen suoritusteho kasvoi 3,4-kertaisesti moduuleille, jotka aiemmin olivat pullonkauloja peräkkäisessä C++-käsittelyssä. Tail-latenssi (p99) laski 61 %, koska Rustin async-ajoaika pystyi käsittelemään itsenäisiä pyyntöjä samanaikaisesti, kun taas C++ käsitteli laskentaa vaativia tehtäviä omassa säikeessään.

Mikä tärkeämpää, meillä ei ollut nolla samanaikaisuuteen liittyviä virheitä kuuden ensimmäisen tuotantokuukauden aikana. Säikeenrajoitusmalli teki rakenteellisesti mahdottomaksi C++-koodin kutsumisen useista säikeistä, kun taas Rustin tyyppijärjestelmä esti datakilpailut sen puolella rajaa. Tämä oli merkittävä parannus verrattuna aiempaan lähestymistapaamme, jossa yritimme lisätä säikeistystä C++:aan mutexeilla, mikä oli tuottanut kolme kilpailutilannetta yhden vuosineljänneksen aikana.

Insinööritiimi raportoi myös nopeammista iteraatiosykleistä. Rustiin voitiin rakentaa uusia ominaisuuksia täydellä samanaikaisuuden tuella, kun taas nykyiset C++-moduulit jatkoivat toimintaansa ilman muutoksia. Tämä asteittainen strategia merkitsi sitä, että meillä ei koskaan ollut riskialtista "big bang" -muuttoa – vain tasaista, mitattavissa olevaa parannusta.

Usein kysytyt kysymykset

Voiko Rust kutsua yksisäikeisiä C++-kirjastoja ilman muutoksia?

Kyllä, mutta sinun on varmistettava, että kaikki kutsut kyseiseen kirjastoon tulevat yhdestä säikeestä. Vakiomalli on luoda omistettu suoritinsäie, joka sarjoittaa kaikki C++-kutsut kanavan kautta. Rustin asynkronointitehtävät lähettävät pyyntöjä ja odottavat vastauksia estämättä monisäikeistä suoritusaikaa. C++-koodi itsessään ei vaadi muutoksia – turvallisuusrajoitus on pakotettu kokonaan ruosteen puolelle.

Onko FFI-ylimäärä tarpeeksi merkittävä vaikuttaakseen sovelluksen suorituskykyyn?

Yksittäisillä FFI-kutsuilla on minimaaliset lisäkustannukset – tyypillisesti alle 10 nanosekuntia yksinkertaisessa funktiokutsussa. Kuitenkin monimutkaisten tietorakenteiden sarjoittaminen ja säikeiden synkronointi rajalla summautuvat, jos teet tuhansia hienojakoisia puheluita. Erätoiminnot ja nollakopioiden serialisointimuotojen, kuten FlatBuffers tai Cap'n Proto, käyttö pitävät yleiskustannukset merkityksettömänä jopa mittakaavassa.

Pitäisikö meidän kirjoittaa C++-koodikanta uudelleen Rustissa rajapinnan sijaan?

Useimmille tiimeille asteittainen käyttöliittymä on turvallisempi ja nopeampi tapa. Täysi uudelleenkirjoitus tuo mukanaan kuukausien suunnitteluriskin ilman käyttäjäkohtaista arvoa ennen valmistumista. Rajapinnan avulla voit lähettää parannuksia välittömästi, validoida Rust-lähestymistavan tuotannossa ja siirtää moduuleja yksi kerrallaan sen mukaan, missä samanaikaisuudella on suurin vaikutus. Kirjoita uudelleen vain ne moduulit, joissa FFI-rajan ylläpitokustannukset ylittävät uudelleenkirjoittamisen kustannukset.


Mewayzillä rakennamme infrastruktuuria, joka skaalautuu sekä teknisesti että toiminnallisesti. 207 moduulin yrityskäyttöjärjestelmämme auttaa 138 000 tiimiä suorittamaan älykkäämpiä työnkulkuja alkaen 19 dollarista kuukaudessa. Hallitsetpa projekteja, automatisoit toimintoja tai skaalaat liiketoimintaasi, Mewayz mukautuu työskentelytapasi mukaan. Aloita ilmainen kokeilujakso osoitteessa app.mewayz.com ja katso, mitä moderni yrityskäyttöjärjestelmä voi tehdä tiimillesi.

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