C++ Venemaa: kuidas see oli

Kui nÀidate nÀidendi alguses, et seinal on kood C++ jaoks, siis peab see kindlasti lÔpus teile jalga laskma.

Bjarne Stroustrup

31. oktoobrist kuni 1. novembrini toimus Peterburis C++ Russia Piter konverents – ĂŒks suurimaid programmeerimiskonverentse Venemaal, mille korraldas JUG Ru Group. KĂŒlalislektorite seas on C++ standardimise komitee liikmed, CppCon'i ettekandjad, O'Reilly vĂ€ljaande autorid ja ka selliste projektide hooldajad nagu LLVM, libc++ ja Boost. Konverents on suunatud kogenud C++ arendajatele, kes soovivad sĂŒvendada oma ekspertiisi ja vahetada kogemusi elavas suhtluses. ÜliĂ”pilastele, doktorantidele ja ĂŒlikoolide Ă”ppejĂ”ududele on pakutavad vĂ€ga head allahindlused.

Moskva konverentsi vĂ€ljaannet saab kĂŒlastada juba jĂ€rgmise aasta aprillis, kuid meie ĂŒliĂ”pilased rÀÀgivad, millest huvitavast nad eelmisel ĂŒritusel teada said. 

C++ Venemaa: kuidas see oli

Fotod konverentsi albumist

Meist

Selle postituse eest vastutasid kaks HSE ĂŒliĂ”pilast – Peterburist:

  • Lisa Vasilenko on 4. kursuse bakalaureuseĂŒliĂ”pilane, kes Ă”pib programmeerimiskeelte suunda „Rakendusmatemaatika ja informaatika“ programmis. Tutvudes C++ keelega ĂŒlikooli esimesel kursusel, omandas ta hiljem selle kasutamise kogemuse praktikal töötades. Kirg programmeerimiskeelte, eriti funktsionaalse programmeerimise vastu on mĂ”jutanud ka tema valikuid konverentsidel esitlemiseks.
  • Danya Smirnov on 1. aasta magistrant programmeerimise ja andmeanalĂŒĂŒsi erialal. Juba koolis lahendas ta C++ keeles olĂŒmpiaadiĂŒlesandeid, ja edaspidi seisis see keel pidevalt tema Ă”pingutes, kuni sellest sai tema peamine tööriist. Ta otsustas konverentsist osa vĂ”tta, et oma teadmisi tĂ€iendada ja tutvuda uute vĂ”imalustega.

Fakulteedi uudiskirjas jagatakse tihti teavet haridusĂŒrituste kohta, mis on seotud meie erialaga. Septembris nĂ€gime C++ Russia kohta teavet ja otsustasime registreeruda kuulajateks. See on meie esimene kogemus sarnastes konverentsides osalemiseks.

Konverentsi struktuur

  • Ettekanded

Kahe pĂ€eva jooksul lugesid eksperdid ette 30 ettekannet, kajastades palju pĂ”letavaid teemasid: keele funktsioonide nutikad rakendused praktiliste ĂŒlesannete lahendamiseks, tulevased keeuudised seoses uue standardiga, C++ disaini kompromissid ja ettevaatusabinĂ”ud nende tagajĂ€rgedega tegelemiseks, huvitava projekt arhitektuuri nĂ€ited ning mĂ”ned keele infrastruktuuri sisemised detailid. Samal ajal toimusid 3 ettekannet, enamasti kaks vene keeles ja ĂŒks inglise keeles.

  • Arutelualad

Esitluse jĂ€rel kanti kĂ”ik vastamata kĂŒsimused ja lĂ”petamata arutelud spetsiaalsetesse suhtlusaladele esinejatega, mis olid varustatud markeritahvlitega. Hea viis veeta paus ettekannete vahel meeldivas vestluses.

  • VĂ€lgatusettekanded ja mitteformaalsed arutelud

Kui soovid teha lĂŒhikese ettekande, saad registreeruda markerite tahvlil Ă”htusele Lightning Talk'ile ja saad viie minuti jooksul rÀÀkida kĂ”igest, mis seondub konverentsi teemaga. NĂ€iteks kiire sissejuhatus C++ sanitizers’itesse (mille kohta oli paljudele uut) vĂ”i lugu sinusoidi genereerimise veast, mille saab vaid kuulda, aga mitte nĂ€ha.

Teine formaat on paneeldiskussioon „Komiteega hingede ĂŒle“. Lavale tulevad mĂ”ned standardimise komitee liikmed, projektoril on kamin (ametlikult - hingelise Ă”hkkonna loomiseks, kuid pĂ”hjus „sest KÕIK ON TULES“ tundub huvitavam), kĂŒsimused on standardi ja C++ ĂŒldise visiooni kohta, ilma Ă€gedate tehniliste arutelute ja konfliktideta. Selgus, et komitees on ka elavaid inimesi, kes ei pruugi mĂ”nedes asjades olla tĂ€ielikult kindlad vĂ”i midagi mitte teada.

Arutelu fĂ€nnide seas kestis kolmas ĂŒritus – BOF-seminar "Go versus C++". VĂ”tame Go armastaja ja C++ armastaja, enne sessiooni algust valmistavad nad koos 100500 slaidi teema ĂŒle (nt C++ paketeerimise probleemid vĂ”i Go generikate puudumine), seejĂ€rel arutavad nad elavalt ĂŒksteisega ja publikuga, samal ajal kui publik pĂŒĂŒab mĂ”ista kahte seisukohta. Kui arutelu muutub ebaoluliseks, sekkub moderaator ja lepitab pooled. See formaat venib: mitu tundi pĂ€rast algust oli lĂ€bida vaid pool slaididest. LĂ”ppu tuli tĂ”siselt kiirendada.

  • Partnerite stendid

KĂ€iguteedes olid esindatud konverentsi partnerid – stendidel rÀÀgiti kĂ€imasolevatest projektidest, pakuti praktikakohti ja tööleasumise vĂ”imalusi, korraldati viktoriine ja vĂ€ikeseid vĂ”istlusi ning loosi anti meeldivaid auhindu. Samuti pakkusid mĂ”ned ettevĂ”tted vĂ”imalust lĂ€bida esimesed vestlusetapid, mis vĂ”ib olla kasulik neile, kes tulid mitte ainult ettekandeid kuulama.

Ettekannete tehnilised ĂŒksikasjad

Kuulasime ettekandeid kogu pĂ€eva. MĂ”nikord oli raske valida ĂŒhte ettekannet samal ajal toimuvate seast – leppisime kokku, et jagame vahel oma teadmisi. Ja isegi nii tundub, et palju jĂ€i puudu. Siin tahaksime rÀÀkida mĂ”nest ettekandest, mis tundusid meile kĂ”ige huvitavamad.

C++ erandid kompilaatori optimeerimise vaatenurgast, Roman Rusajev

C++ Venemaa: kuidas see oli
Slide esitluses

Nagu pealkirjast selgelt nÀha, kÀsitles Roman exceptionide töötlemist LLVM nÀitel. Samas vÔib see ettekande anda mÔningast arusaamist ka neile, kes ei kasuta oma töös Clang'i, kuidas kood vÔiks potentsiaalselt olla optimeeritud. See on nii, sest kompilaatiorite ja vastavate standardraamatukogude arendajad suhtlevad omavahel ja paljusid hÀid lahendusi vÔivad kasutada erinevad meeskonnad.

Seega, erandi kĂ€sitlemiseks on vaja teha mitmeid toiminguid: kutsuda vĂ€lja töötlemiskood (kui see on olemas) vĂ”i vabastada ressursid kĂ€imasolevas tasemes ja kerida stekki ĂŒlespoole. KĂ”ik see viib selleni, et potentsiaalselt erandeid tekitavate kĂ”nede jaoks lisab kompilaator tĂ€iendavaid instruktsioone. Seega, kui erand ei toimu, hakkab programm ikkagi tĂ€itma tarbetuid toiminguid. Ühenduse kulude vĂ€hendamiseks on LLVM-is mitmeid heuristilisi meetodeid, et mÀÀrata olukordi, kus erandite töötlemise koodi ei ole vaja lisada vĂ”i mille puhul vĂ”ib vĂ€hendada â€žĂŒlemÀÀraste“ instruktsioonide arvu.

Ettekandja uurib umbes kĂŒmmet neist ning nĂ€itab, kuidas situatsioonid, kus need aitavad programmi tĂ€itmist kiirendada, ning neid, kus need meetodid ei ole rakendatavad.

Seega toob Roman Russaiev kuulajate ette jÀrelduse, et kood, mis sisaldab töötlemist eranditega, ei pruugi alati olla teostatav nullkulusid kandva operatsioonina ning annab jÀrgmised nÀpunÀited:

  • teeksite raamatukogude arendamisel pĂ”himĂ”tteliselt loobuda eranditest;
  • kui erandid on siiski vajalikud, siis tuleks vĂ”imaluse korral igal pool lisada modifikaatoreid noexcept (ja const), et kompilator saaks vĂ”imalikult palju optimeerida.

KokkuvĂ”ttes kinnitas ettekandja arvamust, et erandeid tuleks kasutada vĂ”imalikult vĂ€he vĂ”i neist ĂŒldse loobuda.

Ettekande slaidid on saadaval lingil: [«C++ erandid LLVM kompilaatori optimeerimise prismast»]

Generators, coroutines ja muud aju avardavad meeldimised, Adi Shavit

C++ Venemaa: kuidas see oli
Slide esitluses

Üks paljusid konverentsi ettekandeid, mis kĂ€sitlevad C++20 uuendusi, jÀÀb meelde mitte ainult vĂ€rvikalt kujundatud esituse, vaid ka selge probleemide mÀÀratlemise tĂ”ttu kogu kollektsioonide töötlemise loogikas (for tsĂŒkkel, tagasiside-d).

Adi Shavit toob vĂ€lja jĂ€rgmised: praegu kasutatavad meetodid lĂ€bivad kogu kogumi ning ei pruugi anda juurdepÀÀsu teatud sisemisele vaheolekule (vĂ”i annavad seda callback-ide kaudu, kuid koos paljude ebameeldivate kĂ”rvalmĂ”judega, nagu Callback Hell). Tundub, et iteratoore on olemas, kuid ka nendega ei ole kĂ”ik nii sujuv: pole ĂŒldisi sisse- ja vĂ€ljapÀÀsukohasid (begin → end versus rbegin → rend jne), ebaselge on, kui palju me ĂŒldse iteratsiooni peame? Alates C++20 lahendatakse need probleemid!

Esimene variant: ranges. Iteraatorite kohal oleva ĂŒmbriku abil saame ĂŒldise liidese iteratsiooni alguse ja lĂ”pu jaoks, samuti vĂ”imaluse kompositsiooniks. KĂ”ik see vĂ”imaldab kergesti ehitada tĂ€islahendusega andmetöötluse torujuhtmeid. Kuid mitte kĂ”ik ei ole nii sujuv: osa arvutuste loogikast vĂ”ib paikneda konkreetse iteratori rakenduses, mis vĂ”ib muuta koodi mĂ”istmise ja silumise keerulisemaks.

C++ Venemaa: kuidas see oli
Slide esitluses

Noh, selleks on C++20-sse lisatud korutiinid (funktsioonid, mille kĂ€itumine sarnaneb Pythonis kasutatavatele generaatoritele): tĂ€itmine saab olla edasi lĂŒkatud, tagastades mĂ”ningase praeguse vÀÀrtuse ja sĂ€ilitades samal ajal vaheoleku. Nii saavutame mitte ainult andmetega töötamise nende saabumisel, vaid ka kogu loogika kapseldamise konkreetse korutiini sisse.

Kuid on ka negatiivne kĂŒlg: praegu toetavad neid vaid osaliselt olemasolevad kompilaatorid ja need on teostatud mitte nii hoolikalt, nagu sooviks: nĂ€iteks ei tasu korutiinides kasutada viiteid ja ajutisi objekte. Pluss, on mĂ”ned piirangud, mis vĂ”ivad olla korutiinid, ja constexpr-funktsioonid, konstruktorid/destruktorid ning ka main ei kuulu sellesse nimekirja.

Seega lahendavad korutiinid mÀrkimisvÀÀrse osa andmete töötlemise loogika lihtsustamise probleemidest, kuid nende praegused teostused vajavad tÀiendavat tööd.

Materjalid:

C++ trikid Yandex.Taxis, Anton Poluhhin

Oma professionaalses tegevuses peab vahel tegelema puhtalt abifunktsioonidega: rakendama mingi teegi sisemise liidese ja API vahel, logimist vĂ”i parsimist. Sel juhul ei ole tavaliselt vajalik mingisugune tĂ€iendav optimeerimine. Aga mis siis, kui neid komponente kasutatakse mĂ”nedes populaarseimates teenustes Ruunetis? Sellises olukorras tuleb töödelda terabaitide kaupa logisid tunnis! Siis on iga millisekund oluline ja seetĂ”ttu tuleb kasutada erinevaid nippe — just neist rÀÀkis Anton Poluhin.

VÔib-olla oli kÔige huvitavam nÀide pointer-to-implementation (pimpl) mustri rakendamine. 

#include <third_party/json.hpp> //PROBLEMS! 
struct Value { 
    Value() = default; 
    Value(Value&& other) = default; 
    Value& operator=(Value&& other) = default; 
    ~Value() = default; 

    std::size_t Size() const { return data_.size(); } 

private: 
    third_party::Json data_; 
};

Selles nĂ€ites tahaks esialgu vabaneda vĂ€liste raamatukogude pealkirjafailidest — see kiirendab kompileerimist ja samuti kaitseb vĂ”imalike nimede konfliktide ja teiste sarnaste vigade eest. 

HĂ€sti, viisime #include cpp-faili: vajalik on edasine dekleerimine ĂŒmbritsetud API-st ning std::unique_ptr. NĂŒĂŒd on meil dĂŒnaamilised allokatsioonid ja muud ebameeldivad asjad, nagu laiali hajutatud andmed pĂ”hjas ja vĂ€henenud garantii. KĂ”ik selle jaoks vĂ”ib aidata std::aligned_storage. 

struct Value { 
// ... 
private: 
    using JsonNative = third_party::Json; 
    const JsonNative* Ptr() const noexcept; 
    JsonNative* Ptr() noexcept; 

    constexpr std::size_t kImplSize = 32; 
    constexpr std::size_t kImplAlign = 8; 
    std::aligned_storage_t data_; 
};

Ainus probleem: iga ĂŒmbriku jaoks tuleb mÀÀrata suurus ja joondamine — teeme meie pimpl mallina parameetritega , kasutame mĂ”ningate suvaliste vÀÀrtuste jaoks ja lisame destruktorisse kontrolli, et kĂ”ik oleks Ă”igesti Ă€ra arvatud: 

~FastPimpl() noexcept { 
    validate(); 
    Ptr()->~T(); 
}

template 
static void validate() noexcept { 
    static_assert(
        Size == ActualSize, 
        "Suurus ja sizeof(T) ei ĂŒhti"
    ); 
    static_assert(
        Alignment == ActualAlignment, 
        "Joondamine ja alignof(T) ei ĂŒhti"
    ); 
}

Kuna T on destruktori töötlemisel juba mÀÀratletud, töötab see kood Ă”igesti ja kompilatsioonietapis kuvab vajalikud suuruse ja joondamise vÀÀrtused, mis tuleb kirjutada. Nii saame ĂŒhe tĂ€iendava kompileerimise hinnaga vabaneda juurdehindlusest pakendatud klasside dĂŒnaamilise eraldamise eest, peidame API .cpp-faili rakendusse ning saame protsessorile paremini vahemĂ€lu sobiva struktuuri.

Logimine ja analĂŒĂŒs tundusid vĂ€hem muljetavaldavad, seega ei mainita neid selles ĂŒlevaates.

Ettekande slaidid on saadaval lingil: [«C++ trikid Taksi»]

Kaasaegsed tehnikad oma koodi kuivana hoidmiseks, Björn Fahller

Selles ettekandes nÀitab Björn Fahller mitmeid erinevaid viise, kuidas vÔidelda selliste stilistiliste puudustega nagu korduvate tingimuste kontrollimine:

assert(a == IDLE || a == CONNECTED || a == DISCONNECTED);

Kas see on tuttav? Kasutades mitmeid vÔimsaid C++ tehnikaid, mis on ilmunud hiljutistes standardites, saab sama funktsionaalsuse elegantsetel viisidel rakendada ilma igasuguste jÔudluskadudeta. VÔrdle:   

assert(a == any_of(IDLE, CONNECTED, DISCONNECTED));

Ebakindla arvu kontrollide haldamiseks tahaksime kasutada variadic templates ja fold expressions. Oletame, et soovime vĂ”rrelda mitme muutuja vĂ”rdsust enum’i state_type elemendiga. Esimene asi, mis pĂ€he tuleb – kirjutada abifunktsioon is_any_of:


enum state_type { IDLE, CONNECTED, DISCONNECTED };

template <typename ... Ts>
bool is_any_of(state_type s, const Ts& ... ts) { 
    return ((s == ts) || ...); 
}

Selline vahepealne tulemus on pettumust valmistav. Kood ei muutu senimaani loetavamaks:

assert(is_any_of(state, IDLE, DISCONNECTING, DISCONNECTED)); 

Non-type mallikparameetrite abil on vÔimalik veidi olukorda parandada. Nende abil edastame enum'ist loetletud elemendid malliparameetrite nimekirja: 

template 
bool is_any_of(state_type t) { 
    return ((t == states) | ...); 
}

assert(is_any_of(state)); 

C++17 versioonis auto kasutamisega mitte-tĂŒĂŒpilise malliparameetri (non-type template parameter) kasutamine laiendab lĂ€henemist nii, et saame vĂ”rrelda mitte ainult state_type elemente, vaid ka primitiivsete tĂŒĂŒpidega, mida saab kasutada mitte-tĂŒĂŒpiliste malliparameetrite jaoks:


template 
bool is_any_of(const T& t) {
    return ((t == alternatives) | ...);
}

Nende jĂ€rjestikuste paranduste kaudu saavutatakse soovitud sujuv sĂŒntaks kontrollide jaoks:


template 
struct any_of : private std::tuple { 
// oleme laisad ja pÀrime tuple'ist konstruktorid 
        using std::tuple::tuple;
        template 
        bool operator ==(const T& t) const {
                return std::apply(
                        [&t](const auto& ... ts) {
                                return ((ts == t) || ...);
                        },
                        static_cast<const std::tuple&>(*this));
        }
};

template 
any_of(Ts ...) -> any_of;

assert(any_of(IDLE, DISCONNECTING, DISCONNECTED) == state);

Selles nĂ€ites on deduktioonijuhend mĂ”eldud kompilaatori jaoks soovitud malliparameetrite struktuuri nĂ€itamiseks, teades konstruktorite argumentide tĂŒĂŒpe. 

Edasi – on huvitavam. Björn Ă”petab kokku vĂ”tma tekkinud koodi vĂ”rreldes teiste vĂ”rdlusoperaatoritega peale ==, ja seejĂ€rel ka erinevate operatsioonidega. Samuti tutvustatakse nĂ€ite kaudu selliseid omadusi nagu no_unique_address atribuut (C++20) ja malliparameetrid lambda-funktsioonides (C++20). (Jah, nĂŒĂŒd on lambda sĂŒntaks veel lihtsam meelde jĂ€tta – see on neli jĂ€rjestikust sulgude paari kĂ”ikidest sortidest.) LĂ”pplahendus, mis kasutab funktsioone kui ehitusdetailideks, rÔÔmustab mind tĂ”eliselt, rÀÀkimata tupelise vĂ€ljendi kasutamisest lambda-arvutuse parimate traditsioonide jĂ€rgi.

LÔpus ei unusta me ilustamisega tegeleda:

  • Kordame, et lambdad on - constexpr tasuta; 
  • Lisame perfect forwarding’i ja vaatame selle koledat sĂŒntaksit seoses parameter pack’iga lambda sulgudes;
  • Anname kompilaatorile rohkem vĂ”imalusi optimeerimiseks conditional noexcept’i abil; 
  • Mugime selgeid tagastavaid vÀÀrtusi lambdade abil, et parandada vigade arusaadavust mallides. See sunnib kompilaatorit tegema rohkem kontrollimisi enne mallifunktsiooni vĂ€ljakutset - tĂŒĂŒbi kontrollimise etapis. 

Lisainformatsiooni saamiseks pöörduge loengumaterjalide poole: 

Meie muljed

Meie esimene osalemine C++ Russia jÀÀb meelde oma sisukuse poolest. C++ Russia jĂ€tab mulje sĂŒdamlikust ĂŒritusest, kus Ă”ppe ja elava suhtluse piir on peaaegu tajumatu. KĂ”ik, alates ettekandjate meeleolust kuni ĂŒrituse partnerite korraldatud konkurssideni, kutsub esile elavaid arutelusid. Konverentsi sisu, mis koosneb ettekannetest, katab ĂŒsna laia teemaspektrit, sealhulgas C++ uuendusi, praktilisi nĂ€iteid suurematest projektidest ja ideoloogilisi arhitektuurilisi kaalutlusi. Kuid oleks ebaĂ”iglane unustada ĂŒrituse sotsiaalset aspekti, mis aitab ĂŒletada keelebarjÀÀre mitte ainult C++ osas.

TĂ€name konverentsi korraldajaid sellise sĂŒndmuse korraldamise vĂ”imaluse eest!
Korraldajate postitus mineviku, oleviku ja tuleviku kohta C++ Russia oli nÀhtav JUG Ru blogis.

AitĂ€h lugemise eest, loodame, et meie sĂŒndmuste kokkuvĂ”te on olnud kasulik!

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster