Kā mēs pārtulkojām 10 miljonus C++ koda rindiņu uz C++14 standartu (un pēc tam uz C++17)

Pirms kāda laika (2016. gada rudenÄ«), izstrādājot 1C:Enterprise tehnoloÄ£iju platformas nākamo versiju, izstrādes komandā radās jautājums par jaunā standarta atbalstÄ«Å”anu. C ++ 14 mÅ«su kodā. Pāreja uz jaunu standartu, kā mēs pieņēmām, ļautu mums daudz ko uzrakstÄ«t elegantāk, vienkārŔāk un uzticamāk, kā arÄ« vienkārÅ”otu koda atbalstu un uzturÄ“Å”anu. Un Ŕķiet, ka tulkojumā nav nekā ārkārtēja, ja ne koda bāzes mērogs un mÅ«su koda Ä«paŔās iezÄ«mes.

Tiem, kas nezina, 1C:Enterprise ir vide ātrai starpplatformu biznesa lietojumprogrammu izstrādei un izpildlaikam to izpildei dažādās operētājsistēmās un DBVS. Kopumā produkts satur:

  • Lietojumprogrammu serveru klasteris, darbojas operētājsistēmās Windows un Linux
  • Klients, strādā ar serveri, izmantojot http(s) vai savu bināro protokolu, darbojas operētājsistēmās Windows, Linux, macOS
  • Web klients, darbojas pārlÅ«kprogrammās Chrome, Internet Explorer, Microsoft Edge, Firefox, Safari (rakstÄ«ts JavaScript)
  • AttÄ«stÄ«bas vide (Konfigurators), darbojas operētājsistēmās Windows, Linux, macOS
  • AdministrÄ“Å”anas rÄ«ki lietojumprogrammu serveri, darbojas operētājsistēmās Windows, Linux, macOS
  • Mobilais klients, izveido savienojumu ar serveri, izmantojot http(s), darbojas mobilajās ierÄ«cēs, kurās darbojas Android, iOS, Windows
  • Mobilā platforma ā€” ietvars bezsaistes mobilo lietojumprogrammu izveidei ar iespēju sinhronizēt, darbojas operētājsistēmās Android, iOS, Windows
  • AttÄ«stÄ«bas vide 1C: uzņēmuma attÄ«stÄ«bas rÄ«ki, rakstÄ«ts Java valodā
  • Serveris MijiedarbÄ«bas sistēmas

Mēs cenÅ”amies pēc iespējas vairāk rakstÄ«t vienu un to paÅ”u kodu dažādām operētājsistēmām - servera kodu bāze ir 99% kopÄ«ga, klienta kodu bāze ir aptuveni 95%. 1C:Enterprise tehnoloÄ£iju platforma galvenokārt ir rakstÄ«ta C++ valodā, un aptuvenās koda Ä«paŔības ir norādÄ«tas zemāk:

  • 10 miljoni C++ koda rindiņu,
  • 14 tÅ«kstoÅ”i failu,
  • 60 tÅ«kstoÅ”i nodarbÄ«bu,
  • pusmiljons metožu.

Un visas Ŕīs lietas bija jātulko C++14 valodā. Å odien mēs jums pastāstÄ«sim, kā mēs to izdarÄ«jām un ar ko saskārāmies Å”ajā procesā.

Kā mēs pārtulkojām 10 miljonus C++ koda rindiņu uz C++14 standartu (un pēc tam uz C++17)

Atruna

Viss, kas rakstÄ«ts zemāk par lēnu/ātro darbu, (ne) lielo atmiņas patēriņu, ievieÅ”ot standarta klases dažādās bibliotēkās, nozÄ«mē vienu: tas attiecas uz MUMS. PilnÄ«gi iespējams, ka standarta implementācijas bÅ«s vispiemērotākās jÅ«su uzdevumiem. Mēs sākām no saviem uzdevumiem: ņēmām datus, kas bija raksturÄ«gi mÅ«su klientiem, palaidām tiem tipiskus scenārijus, apskatÄ«jām veiktspēju, patērētās atmiņas apjomu utt. un analizējām, vai mēs un mÅ«su klienti esam apmierināti ar Ŕādiem rezultātiem vai nē. . Un viņi rÄ«kojās atkarÄ«bā no.

Kas mums bija

Sākotnēji mēs rakstÄ«jām kodu platformai 1C: Enterprise 8, izmantojot Microsoft Visual Studio. Projekts sākās 2000. gadu sākumā, un mums bija tikai Windows versija. Protams, kopÅ” tā laika kods ir aktÄ«vi izstrādāts, daudzi mehānismi ir pilnÄ«bā pārrakstÄ«ti. Bet kods tika uzrakstÄ«ts pēc 1998. gada standarta, un, piemēram, mÅ«su taisnleņķa iekavas tika atdalÄ«tas ar atstarpēm, lai kompilācija izdotos, piemēram:

vector<vector<int> > IntV;

2006. gadā, izlaižot platformas versiju 8.1, mēs sākām atbalstÄ«t Linux un pārgājām uz treŔās puses standarta bibliotēku. STLPort. Viens no pārejas iemesliem bija darbs ar platām lÄ«nijām. Savā kodā mēs izmantojam std::wstring, kura pamatā ir wchar_t veids. Tā lielums operētājsistēmā Windows ir 2 baiti, un Linux noklusējuma izmērs ir 4 baiti. Tas izraisÄ«ja mÅ«su bināro protokolu nesaderÄ«bu starp klientu un serveri, kā arÄ« dažādus pastāvÄ«gus datus. Izmantojot gcc opcijas, var norādÄ«t, ka arÄ« wchar_t izmērs kompilācijas laikā ir 2 baiti, bet tad var aizmirst par standarta bibliotēkas izmantoÅ”anu no kompilatora, jo tas izmanto glibc, kas savukārt tiek kompilēts 4 baitu wchar_t. Citi iemesli bija labāka standarta klaÅ”u ievieÅ”ana, atbalsts hash tabulām un pat konteineru iekÅ”puses pārvietoÅ”anas semantikas emulācija, ko mēs aktÄ«vi izmantojām. Un vēl viens iemesls, kā saka, pēdējais, bet ne mazāk svarÄ«gais, bija stÄ«gu izpildÄ«jums. Mums bija sava stÄ«gu klase, jo... MÅ«su programmatÅ«ras specifikas dēļ virkņu darbÄ«bas tiek izmantotas ļoti plaÅ”i, un mums tas ir ļoti svarÄ«gi.

MÅ«su virkne ir balstÄ«ta uz virkņu optimizācijas idejām, kas izteiktas 2000. gadu sākumā Andrejs Aleksandresku. Vēlāk, kad Aleksandresku strādāja Facebook, pēc viņa ierosinājuma Facebook dzinējā tika izmantota lÄ«nija, kas darbojās pēc lÄ«dzÄ«giem principiem (sk. bibliotēku muļķība).

Mūsu līnija izmantoja divas galvenās optimizācijas tehnoloģijas:

  1. ÄŖsām vērtÄ«bām tiek izmantots iekŔējais buferis paŔā virknes objektā (nav nepiecieÅ”ama papildu atmiņas pieŔķirÅ”ana).
  2. Visiem pārējiem tiek izmantota mehānika Kopēt uz rakstÄ«Å”anas. Virknes vērtÄ«ba tiek saglabāta vienuviet, un pieŔķirÅ”anas/modifikācijas laikā tiek izmantots atsauces skaitÄ«tājs.

Lai paātrinātu platformas kompilāciju, mēs izslēdzām straumes ievieÅ”anu no mÅ«su STLPort varianta (kuru mēs neizmantojām), tas mums nodroÅ”ināja par aptuveni 20% ātrāku kompilāciju. Pēc tam mums bija jāizmanto ierobežota izmantoÅ”ana Palielināt. Boost intensÄ«vi izmanto straumi, jo Ä«paÅ”i tās pakalpojumu API (piemēram, reÄ£istrÄ“Å”anai), tāpēc mums tas bija jāmaina, lai noņemtu straumes izmantoÅ”anu. Tas savukārt mums apgrÅ«tināja migrÄ“Å”anu uz jaunām Boost versijām.

treŔais ceļŔ

Pārejot uz C++14 standartu, mēs apsvērām Ŕādas iespējas:

  1. Jauniniet STLPort, kuru mēs modificējām, uz C++14 standartu. Variants ir ļoti grÅ«ts, jo... STLPort atbalsts tika pārtraukts 2010. gadā, un mums paÅ”iem bÅ«tu jāizveido viss tā kods.
  2. Pāreja uz citu STL ievieÅ”anu, kas ir saderÄ«ga ar C++14. Ir ļoti vēlams, lai Ŕī ievieÅ”ana bÅ«tu operētājsistēmai Windows un Linux.
  3. Kompilējot katrai OS, izmantojiet atbilstoÅ”ajā kompilatorā iebÅ«vēto bibliotēku.

Pirmais variants tika pilnībā noraidīts pārāk daudz darba dēļ.

Kādu laiku domājām par otro variantu; uzskatÄ«ts par kandidātu libc++, bet tajā laikā tas nedarbojās operētājsistēmā Windows. Lai portētu libc++ uz Windows, jums bÅ«s daudz jāstrādā - piemēram, paÅ”am jāraksta viss, kas saistÄ«ts ar pavedieniem, pavedienu sinhronizāciju un atomitāti, jo Å”ajās jomās tiek izmantots libc++ POSIX API.

Un mēs izvēlējāmies treÅ”o ceļu.

Pāreja

Tātad mums bija jāaizstāj STLPort lietoÅ”ana ar atbilstoÅ”o kompilatoru bibliotēkām (Visual Studio 2015 operētājsistēmai Windows, gcc 7 operētājsistēmai Linux, clang 8 operētājsistēmai macOS).

Par laimi, mÅ«su kods tika rakstÄ«ts galvenokārt saskaņā ar vadlÄ«nijām un tajā netika izmantoti visādi gudri triki, tāpēc migrācija uz jaunām bibliotēkām noritēja salÄ«dzinoÅ”i raiti, izmantojot skriptus, kas aizstāja veidu, klaÅ”u, nosaukumvietu nosaukumus un ietver avotā. failus. Migrācija skāra 10 000 avota failu (no 14 000). wchar_t tika aizstāts ar char16_t; mēs nolēmām atteikties no wchar_t lietoÅ”anas, jo char16_t visās operētājsistēmās aizņem 2 baitus un nesabojā koda saderÄ«bu starp Windows un Linux.

Bija daži nelieli piedzÄ«vojumi. Piemēram, STLPort iterators var tikt netieÅ”i nodots rādÄ«tājam uz elementu, un dažās mÅ«su koda vietās tas tika izmantots. Jaunajās bibliotēkās to vairs nebija iespējams izdarÄ«t, un Å”ie fragmenti bija jāanalizē un jāpārraksta manuāli.

Tātad koda migrācija ir pabeigta, kods ir apkopots visām operētājsistēmām. Ir pienācis laiks testiem.

Pārbaudes pēc pārejas uzrādÄ«ja veiktspējas kritumu (dažās vietās lÄ«dz 20-30%) un atmiņas patēriņa pieaugumu (lÄ«dz 10-15%), salÄ«dzinot ar veco koda versiju. Tas jo Ä«paÅ”i bija saistÄ«ts ar standarta stÄ«gu neoptimālo veiktspēju. Tāpēc atkal nācās izmantot savu, nedaudz pārveidoto lÄ«niju.

Tika atklāta arÄ« interesanta konteineru ievieÅ”anas iezÄ«me iegultajās bibliotēkās: tukÅ”a (bez elementiem) std::map un std::set no iebÅ«vētajām bibliotēkām pieŔķir atmiņu. Un ievieÅ”anas pazÄ«mju dēļ dažās vietās kodā tiek izveidots diezgan daudz tukÅ”u Ŕāda veida konteineru. Standarta atmiņas konteineri ir atvēlēti nedaudz, vienam saknes elementam, bet mums tas izrādÄ«jās kritiski - vairākos scenārijos mÅ«su veiktspēja ievērojami samazinājās un atmiņas patēriņŔ palielinājās (salÄ«dzinot ar STLPort). Tāpēc savā kodā mēs aizstājām Å”os divu veidu konteinerus no iebÅ«vētajām bibliotēkām ar to ievieÅ”anu no Boost, kur Å”iem konteineriem nebija Ŕīs funkcijas, un tas atrisināja problēmu ar palēnināŔanos un palielinātu atmiņas patēriņu.

Kā tas bieži notiek pēc liela mēroga izmaiņām lielos projektos, pirmā avota koda iterācija nedarbojās bez problēmām, un Å”eit jo Ä«paÅ”i noderēja iteratoru atkļūdoÅ”anas atbalsts Windows ievieÅ”anā. Soli pa solim mēs virzāmies uz priekÅ”u, un lÄ«dz 2017. gada pavasarim (versija 8.3.11 1C:Enterprise) migrÄ“Å”ana tika pabeigta.

Rezultāti

Pāreja uz C++14 standartu mums aizņēma aptuveni 6 mēneÅ”us. Lielāko daļu laika pie projekta strādāja viens (bet ļoti augsti kvalificēts) izstrādātājs, un beigu posmā pievienojās par konkrētām jomām atbildÄ«go komandu pārstāvji - UI, serveru klasteris, izstrādes un administrÄ“Å”anas rÄ«ki utt.

Pāreja ievērojami vienkārÅ”oja mÅ«su darbu pie migrācijas uz jaunākajām standarta versijām. Tādējādi versija 1C:Enterprise 8.3.14 (izstrādē, izlaiÅ”ana paredzēta nākamā gada sākumā) jau ir pārcelta uz standartu C++17.

Pēc migrācijas izstrādātājiem ir vairāk iespēju. Ja agrāk mums bija sava modificētā STL versija un viena std nosaukumvieta, tad tagad mums ir standarta klases no iebÅ«vēto kompilatoru bibliotēkām std nosaukumvietā, stdx nosaukumvietā - mÅ«su rindas un konteineri, kas optimizēti mÅ«su uzdevumiem, pastiprinājumā - jaunākā pastiprināŔanas versija. Un izstrādātājs izmanto tās klases, kas ir optimāli piemērotas viņa problēmu risināŔanai.

PārvietoÅ”anās konstruktoru ā€œvietējāā€ ievieÅ”ana palÄ«dz arÄ« attÄ«stÄ«bā (pārvietot konstruktorus) vairākām klasēm. Ja klasei ir pārvietoÅ”anas konstruktors un Ŕī klase ir ievietota konteinerā, tad STL optimizē elementu kopÄ“Å”anu konteinera iekÅ”ienē (piemēram, kad konteiners tiek paplaÅ”ināts un nepiecieÅ”ams mainÄ«t ietilpÄ«bu un pārdalÄ«t atmiņu).

Lidot ziedi

Iespējams, visnepatÄ«kamākās (bet ne kritiskās) migrācijas sekas ir tās, ka mēs saskaramies ar apjoma pieaugumu obj faili, un pilns bÅ«vÄ“Å”anas rezultāts ar visiem starpfailiem sāka aizņemt 60ā€“70 GB. Šāda uzvedÄ«ba ir saistÄ«ta ar mÅ«sdienu standarta bibliotēku Ä«patnÄ«bām, kuras ir kļuvuÅ”as mazāk kritiskas pret Ä£enerēto pakalpojumu failu lielumu. Tas neietekmē kompilētās lietojumprogrammas darbÄ«bu, taču tas rada vairākas neērtÄ«bas izstrādē, jo Ä«paÅ”i palielina kompilācijas laiku. Pieaug arÄ« prasÄ«bas pēc brÄ«vas diska vietas build serveros un izstrādātāju iekārtās. MÅ«su izstrādātāji paralēli strādā pie vairākām platformas versijām, un simtiem gigabaitu starpposma failu dažkārt rada grÅ«tÄ«bas viņu darbā. Problēma ir nepatÄ«kama, bet ne kritiska; pagaidām esam atlikuÅ”i tās risināŔanu. Mēs apsveram tehnoloÄ£iju kā vienu no iespējām tās risināŔanai vienotÄ«bas veidoÅ”ana (jo Ä«paÅ”i Google to izmanto, izstrādājot pārlÅ«ku Chrome).

Avots: www.habr.com

Pievieno komentāru