Hacker News

Ni interfacigis unu-fadenan C++ kun mult-fadena Rust

Ni interfacigis unu-fadenan C++ kun mult-fadena Rust Ĉi tiu ampleksa analizo de interfaca ofertas detalan ekzamenon de siaj kernkomponentoj kaj pli larĝajn implicojn. Ŝlosilaj Areoj de Fokuso La diskuto centras sur: Kerna mekanismo...

7 min read Via antithesis.com

Mewayz Team

Editorial Team

Hacker News
Jen la kompleta blogo pri SEO:

Ni Interfacigis Unufadenan C++ kun Plurfadena Rusto

Interfacado de unufadena C++-kodo kun plurfadena Rusto ne nur eblas — ĝi estas unu el la plej praktikaj manieroj modernigi heredajn sistemojn sen plena reverko. Ĉe Mewayz, ni traktis ĉi tiun precizan defion dum skalado de nia 207-modula komerca OS por servi 138,000 uzantojn, kaj la rezultoj esence ŝanĝis kiel ni pensas pri sistema kunfunkciebleco.

Kial Vi Interfagus Unufadenan C++ kun Plurfadena Rusto?

Plej multaj produktadsistemoj portas jarojn da batalprovita C++-kodo. Reskribi ĉion en Rust sonas alloga sur papero, sed ĝi enkondukas masivan riskon kaj monatojn da inĝenieristiko. La pragmata aliro estas pliiga adopto — envolvi ekzistantan C++-logikon dum malŝarĝo de samtempaj pezaj laborŝarĝoj al la poseda modelo de Rust.

En nia kazo, kernaj komercaj logikmoduloj funkciis fidinde en unufadena C++ dum jaroj. Ili pritraktis sinsekvan taskopretigon, dokumentgeneradon, kaj financajn kalkulojn. Sed ĉar nia uzantbazo kreskis preter 100K, ni bezonis paralelan datumtraktadon, samtempan API-traktadon kaj sekuran kunŝtatan administradon. La trajtoj de Rust Sendu kaj Sinkronigi donis al ni kompiltempajn samtempajn garantiojn, kiujn C++ simple ne povus oferti sen ampleksa mana revizio.

La ŝlosila instigo estas riskoredukto. Vi konservas tion, kio funkcias, kaj vi aldonas kiajn skalojn — sen hazardludo de via tuta kodbazo je migrado, kiu eble neniam finiĝos.

Kiel Funkcias la FFI-Limo Efektive?

La Foreign Function Interface (FFI) inter C++ kaj Rust funkcias per C-kongruaj funkciosubskriboj. La eksteraj "C" blokoj de Rust elmontras funkciojn kiujn C++ povas voki rekte, kaj inverse. La kritika defio aperas kiam la plurfadena rultempo de Rust bezonas sekure alvoki unufadenan C++-kodon.

Ni solvis ĉi tion uzante dediĉitan arkitekturon:

  • Faden-limigita C++-ekzekutanto: Ĉiuj C++-vokoj estas enkanaligataj tra ununura dediĉita fadeno uzante mesaĝ-pasantan kanalon, certigante ke la unufadena senvarianto neniam estas malobservita.
  • Rust nesinkrona ponttavolo: Tokio-taskoj sendas laboron al la C++-ekzekutanto kaj atendas rezultojn per unufojaj kanaloj, tenante la Rust-flankon plene nesinkrona.
  • Opaka montrilo-administrado: C++-objektoj estas envolvitaj en Rust-strukturoj kiuj efektivigas Faligi por determinisma purigado, malhelpante memorfuĝojn trans la lingvolimo.
  • Seriligo ĉe la limo: Kompleksaj datumstrukturoj estas seriigitaj al FlatBuffers ĉe la FFI-tavolo, evitante delikatan strukturan aranĝon kongruon kaj ebligante sendependan evoluon de ĉiu flanko.
  • Panika izolado: Rust catch_unwind envolvas ĉiun FFI-enirpunkton tiel ke paniko neniam transpasas la lingvan limon, kio estus nedifinita konduto.

Ĉi tiu ŝablono donis al ni la trairon de multfadena Rust kun la fidindeco de pruvita C++-logiko — sen reverki ununuran linion de la originaj komercaj reguloj.

Kiuj Estas la Plej Grandaj Kapabloj Evitindaj?

La plej danĝera eraro estas supozi ke C++-kodo estas fadenprotekta kiam ĝi ne estas. Tutmonda stato, senmovaj variabloj kaj ne-reenirantaj bibliotekvokoj kaŭzos datumvetkurojn kiujn la kompililo de Rust ne povas detekti trans la FFI-limo. La sekurecaj garantioj de Rust ĉesu ĉe la nesekura bloko — ĉio ene estas via respondeco.

Ŝlosila kompreno: Rust garantias memorsekurecon ene de sia propra kodo, sed kiam vi transiras FFI-limon en C++, vi heredas ĉiun fadensekurecan problemon kiun C++ havas. La arkitekturo ĉirkaŭ tiu limo gravas pli ol la kodo ambaŭflanke de ĝi.

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

Alia ofta malfacilaĵo estas dumviva administrado. C++-objektoj ne partoprenas en la pruntkontrolilo de Rust. Se Rust faligas referencon dum C++ ankoraŭ tenas montrilon, vi ricevas senpagajn cimojn, kiuj estas brutale malfacile diagnozeblaj. Ni traktis ĉi tion per devigado de strikta poseda semantiko: C++-objektoj ĉiam estas posedataj de ekzakte unu Rust-envolvaĵo, kaj komuna aliro pasas per Ark-bazita referenco kalkulanta sur la Rust-flanko.

Efikec-saĝaj, troaj FFI-vokoj kreas superŝarĝon de kunteksta ŝanĝado kaj seriigo. Ni grupigas operaciojn kie ajn eblas, sendante vicon da laboraĵoj al la C++-ekzekutanto anstataŭ fari individuajn translingvajn vokojn.

Kiel Funkciis Ĉi tiu Aliro en Produktado?

Post deplojado de la hibrida arkitekturo tra nia platformo, ni mezuris konkretajn plibonigojn. Peto-trairo pliigita je 3.4x por moduloj, kiuj antaŭe malrapidiĝis pri sinsekva C++-pretigo. Vosto latenteco (p99) malpliiĝis je 61% ĉar la nesinkrona rultempo de Rust povis procesi sendependajn petojn samtempe dum C++ pritraktis komputad-pezajn taskojn sur sia dediĉita fadeno.

Pli grave, ni havis nulon samtempajn cimojn en la unuaj ses monatoj de produktado. La faden-limiga padrono igis ĝin strukture malebla ke C++-kodo estus vokita de multoblaj fadenoj, dum la tipsistemo de Rust malhelpis datenvetkurojn sur sia flanko de la limo. Ĉi tio estis signifa plibonigo super nia antaŭa aliro provi aldoni fadenadon al C++ kun muteksoj, kiuj produktis tri raskondiĉajn okazaĵojn en ununura kvarono.

La inĝenieristikteamo ankaŭ raportis pli rapidajn ripetajn ciklojn. Novaj funkcioj povus esti konstruitaj en Rust kun plena samtempa subteno, dum ekzistantaj C++-moduloj daŭre funkciis sen modifo. Ĉi tiu pliiga strategio signifis, ke ni neniam havis alt-riskan "grandan eksplodon" migradon — nur konstantan, mezureblan plibonigon.

Oftaj Demandoj

Ĉu Rust povas voki unufadenajn C++-bibliotekojn sen modifo?

Jes, sed vi devas certigi, ke ĉiuj vokoj al tiu biblioteko okazas el unu fadeno. La norma ŝablono estas krei dediĉitan ekzekutistofadenon kiu seriigas ĉiujn C++-vokojn per kanalo. La nesinkronaj taskoj de Rust sendas petojn kaj atendas respondojn sen bloki la multfadenan rultempon. La C++-kodo mem postulas neniujn ŝanĝojn — la sekureca limo estas devigita tute ĉe la Rust-flanko.

Ĉu la superkosto de FFI estas sufiĉe grava por influi aplikaĵon?

Individuaj FFI-vokoj havas minimuman superkozon — tipe malpli ol 10 nanosekundoj por simpla funkciovoko. Tamen, seriigo de kompleksaj datumstrukturoj kaj fadensinkronigado ĉe la limo sumiĝas se vi faras milojn da fajnaj vokoj. Bataj operacioj kaj uzado de nul-kopia seriigformatoj kiel FlatBuffers aŭ Cap'n Proto tenas superkopi nekonsiderinda eĉ ĉe skalo.

Ĉu ni reverku nian C++-kodbazon en Rust anstataŭ interfacigi?

Por plej multaj teamoj, pliiga interfaco estas la pli sekura kaj rapida vojo. Plena reverko enkondukas monatojn da inĝenieristikrisko kun neniu alfronta valoro ĝis kompletigo. Interfacado ebligas vin sendi plibonigojn tuj, validigi la Rust-aliron en produktado kaj migri modulojn unuope surbaze de kie samtempeco donas la plej grandan efikon. Reskribi nur la modulojn kie la kosto de konservado de la FFI-limo superas la koston de reverkado.


Ĉe Mewayz, ni konstruas infrastrukturon kiu skalas - kaj teknike kaj funkcie. Nia 207-modula komerca OS helpas 138,000-teamojn prizorgi pli inteligentajn laborfluojn ekde $19/monato. Ĉu vi administras projektojn, aŭtomatigas operaciojn aŭ skalas vian komercon, Mewayz adaptiĝas al la maniero kiel vi laboras. Komencu vian senpagan provon ĉe app.mewayz.com kaj vidu, kion moderna komerca OS povas fari por via teamo.