C++ кодының 10 миллион жолын C++14 стандартына (содан кейін C++17 тіліне) қалай аудардық?

Біраз уақыт бұрын (2016 жылдың күзінде) 1C: Enterprise технологиялық платформасының келесі нұсқасын әзірлеу кезінде әзірлеушілер тобында жаңа стандартты қолдау туралы сұрақ туындады. C ++ 14 біздің кодымызда. Жаңа стандартқа көшу, біз ойлағандай, бізге көп нәрсені талғампаз, қарапайым және сенімдірек жазуға мүмкіндік береді және кодты қолдау мен қолдауды жеңілдетеді. Ал аудармада кодтық базаның масштабы мен кодымыздың ерекше ерекшеліктері болмаса, ерекше ештеңе жоқ сияқты.

Білмейтіндер үшін 1С: Кәсіпорын - бұл кросс-платформалық бизнес-қосымшаларды жылдам дамытуға және оларды әртүрлі ОЖ және ДҚБЖ-да орындауға арналған жұмыс уақытына арналған орта. Жалпы алғанда, өнім құрамында:

Біз әртүрлі операциялық жүйелер үшін бірдей кодты мүмкіндігінше жазуға тырысамыз - сервер кодтық базасы 99% жалпы, клиенттік код базасы шамамен 95% құрайды. 1C: Enterprise технологиялық платформасы негізінен C++ тілінде жазылған және шамамен код сипаттамалары төменде келтірілген:

  • C++ кодының 10 миллион жолы,
  • 14 мың файл,
  • 60 мың сынып,
  • жарты миллион әдіс.

Осының барлығын C++ 14 тіліне аудару керек болды. Бүгін біз мұны қалай жасағанымызды және бұл процесте нені кездестіргенімізді айтып береміз.

C++ кодының 10 миллион жолын C++14 стандартына (содан кейін C++17 тіліне) қалай аудардық?

Ескерту

Әртүрлі кітапханалардағы стандартты сыныптарды енгізу арқылы баяу/жылдам жұмыс, (емес) жадты көп тұтыну туралы төменде жазылғанның бәрі бір нәрсені білдіреді: бұл БІЗ ҮШІН дұрыс. Стандартты енгізулер сіздің тапсырмаларыңызға ең қолайлы болуы әбден мүмкін. Біз өз міндеттерімізден бастадық: біз өз клиенттерімізге тән деректерді алдық, олар бойынша типтік сценарийлерді орындадық, өнімділікке, тұтынылатын жад көлеміне және т.б. қарадық және біз және біздің клиенттер мұндай нәтижелерге қанағаттанған-қанағаттанбағанын талдадық. . Және олар байланысты әрекет етті.

Бізде не болды

Бастапқыда біз Microsoft Visual Studio көмегімен 1С: Enterprise 8 платформасының кодын жаздық. Жоба 2000 жылдардың басында басталды және бізде тек Windows нұсқасы болды. Әрине, содан бері код белсенді түрде әзірленді, көптеген механизмдер толығымен қайта жазылды. Бірақ код 1998 стандартына сәйкес жазылған және, мысалы, біздің тік бұрышты жақшаларымыз бос орындармен бөлінген, осылайша компиляция сәтті болады, мысалы:

vector<vector<int> > IntV;

2006 жылы платформаның 8.1 нұсқасының шығуымен біз Linux жүйесіне қолдау көрсете бастадық және үшінші тарап стандартты кітапханасына ауыстық. STLPort. Көшу себептерінің бірі кең сызықтармен жұмыс істеу болды. Біздің кодта біз wchar_t түріне негізделген std::wstring қолданамыз. Windows жүйесінде оның өлшемі 2 байт, ал Linux жүйесінде әдепкі 4 байт. Бұл клиент пен сервер арасындағы екілік протоколдарымыздың, сондай-ақ әртүрлі тұрақты деректердің үйлеспеуіне әкелді. Gcc опцияларын пайдалана отырып, компиляция кезінде wchar_t өлшемі де 2 байт болатынын көрсетуге болады, бірақ содан кейін компилятордан стандартты кітапхананы пайдалануды ұмытуға болады, себебі ол glibc пайдаланады, ол өз кезегінде 4 байт wchar_t үшін құрастырылады. Басқа себептер стандартты сыныптарды жақсырақ енгізу, хэш-кестелерді қолдау және тіпті біз белсенді қолданатын контейнерлер ішінде қозғалу семантикасын эмуляциялау болды. Және тағы бір себеп, олар айтқандай, соңғы, бірақ кем дегенде, жолдың өнімділігі болды. Бізде ішектерге арналған өз сыныбымыз болды, өйткені... Біздің бағдарламалық жасақтаманың ерекшеліктеріне байланысты жолдық операциялар өте кең қолданылады және біз үшін бұл өте маңызды.

Біздің жолымыз 2000-шы жылдардың басында айтылған жолды оңтайландыру идеяларына негізделген Андрей Александреску. Кейінірек, Александреску Facebook-те жұмыс істеген кезде, оның ұсынысы бойынша, Facebook қозғалтқышында ұқсас принциптермен жұмыс істейтін желі қолданылды (кітапхананы қараңыз). ақылсыздық).

Біздің желі екі негізгі оңтайландыру технологиясын пайдаланды:

  1. Қысқа мәндер үшін жол нысанындағы ішкі буфер пайдаланылады (қосымша жадты бөлуді қажет етпейді).
  2. Барлық қалғандары үшін механика қолданылады Көшіру On Write. Жолдың мәні бір жерде сақталады және тағайындау/өзгерту кезінде анықтамалық есептегіш пайдаланылады.

Платформаның компиляциясын жылдамдату үшін біз STLPort нұсқасынан ағынды іске асыруды алып тастадық (біз оны пайдаланбадық), бұл бізге шамамен 20% жылдам құрастыруды қамтамасыз етті. Кейіннен шектеулі пайдалануға тура келді ұлғайту. Boost ағынды, әсіресе оның API қызметінде (мысалы, тіркеу үшін) көп пайдаланады, сондықтан ағынды пайдалануды жою үшін оны өзгертуге тура келді. Бұл, өз кезегінде, бізге Boost-тың жаңа нұсқаларына көшуді қиындатты.

Үшінші жол

C++14 стандартына көшкен кезде біз келесі опцияларды қарастырдық:

  1. Біз өзгерткен STLPort нұсқасын C++ 14 стандартына жаңартыңыз. Опция өте қиын, өйткені... STLPort қолдауы 2010 жылы тоқтатылды және біз оның барлық кодын өзіміз жасауымыз керек еді.
  2. C++ 14 тілімен үйлесімді басқа STL іске асыруға көшу. Бұл енгізудің Windows және Linux үшін болғаны өте жақсы.
  3. Әрбір ОЖ үшін құрастыру кезінде сәйкес компиляторға енгізілген кітапхананы пайдаланыңыз.

Тым көп жұмыс болғандықтан бірінші нұсқа мүлде қабылданбады.

Біз екінші нұсқа туралы біраз уақыт ойладық; кандидат ретінде қарастырылады libc++, бірақ ол кезде Windows жүйесінде жұмыс істемеді. libc++ жүйесін Windows жүйесіне порттау үшін сізге көп жұмыс істеу керек болады - мысалы, ағындарға, ағынды синхрондауға және атомдылыққа қатысты барлық нәрсені өзіңіз жазыңыз, өйткені libc++ осы аймақтарда қолданылады. POSIX API.

Ал біз үшінші жолды таңдадық.

Өтпелі кезең

Осылайша, STLPort пайдалануды сәйкес компиляторлардың кітапханаларымен ауыстыруға тура келді (Windows үшін Visual Studio 2015, Linux үшін gcc 7, macOS үшін clang 8).

Бақытымызға орай, біздің код негізінен нұсқауларға сәйкес жазылған және барлық ақылды трюктерді пайдаланбаған, сондықтан жаңа кітапханаларға көшу типтердің, сыныптардың, аттар кеңістігінің атауларын ауыстыратын және дереккөзге енгізілген сценарийлердің көмегімен салыстырмалы түрде біркелкі өтті. файлдар. Тасымалдау 10 000 бастапқы файлға әсер етті (14 000 файлдан). wchar_t ауыстырылды char16_t; біз wchar_t пайдаланудан бас тартуды шештік, өйткені char16_t барлық операциялық жүйелерде 2 байтты алады және Windows пен Linux арасындағы код үйлесімділігін бұзбайды.

Біраз шытырман оқиғалар болды. Мысалы, STLPort бағдарламасында итераторды жанама түрде элементке көрсеткішке жіберуге болады және біздің кодтың кейбір жерлерінде бұл қолданылған. Жаңа кітапханаларда мұны істеу мүмкін болмады және бұл үзінділерді қолмен талдап, қайта жазу керек болды.

Сонымен, кодты көшіру аяқталды, код барлық операциялық жүйелер үшін құрастырылған. Сынақтардың уақыты келді.

Өтуден кейінгі сынақтар кодтың ескі нұсқасымен салыстырғанда өнімділіктің төмендеуін (кейбір жерлерде 20-30% дейін) және жадты тұтынудың (10-15% дейін) жоғарылауын көрсетті. Бұл, атап айтқанда, стандартты жолдардың оңтайлы емес өнімділігіне байланысты болды. Сондықтан біз қайтадан өзіміздің, сәл өзгертілген желіні қолдануға мәжбүр болдық.

Енгізілген кітапханаларда контейнерлерді жүзеге асырудың қызықты ерекшелігі де анықталды: бос (элементсіз) std::map және std:: орнатылған кітапханалардан жинақталған жадты бөледі. Ал іске асыру мүмкіндіктеріне байланысты кодтың кейбір жерлерінде осы типтегі бос контейнерлер жеткілікті. Стандартты жад контейнерлері бір түбір элементі үшін аздап бөлінген, бірақ біз үшін бұл өте маңызды болды - бірқатар сценарийлерде біздің өнімділігіміз айтарлықтай төмендеді және жадты тұтыну өсті (STLPort-пен салыстырғанда). Сондықтан, біздің кодымызда біз кірістірілген кітапханалардағы контейнерлердің осы екі түрін оларды Boost-тен іске асырумен ауыстырдық, онда бұл контейнерлерде мұндай мүмкіндік жоқ, бұл баяулау және жадты тұтынуды арттыру мәселесін шешті.

Ірі жобалардағы ауқымды өзгерістерден кейін жиі орын алатындай, бастапқы кодтың бірінші итерациясы қиындықсыз жұмыс істемеді және мұнда, атап айтқанда, Windows іске асырудағы итераторларды жөндеуге қолдау көрсету ыңғайлы болды. Біртіндеп алға жылжып, 2017 жылдың көктеміне қарай (8.3.11 1С:Кәсіпорын нұсқасы) көшу аяқталды.

Нәтижелері

C++14 стандартына көшу бізге 6 айға жуық уақытты алды. Көбінесе жобада бір (бірақ өте жоғары білікті) әзірлеуші ​​жұмыс істеді, ал соңғы кезеңде белгілі бір салаларға жауапты топтардың өкілдері қосылды - UI, сервер кластері, әзірлеу және басқару құралдары және т.б.

Өту стандарттың соңғы нұсқаларына көшу бойынша жұмысымызды айтарлықтай жеңілдетті. Осылайша, 1C: Enterprise 8.3.14 нұсқасы (әзірлеуде, шығару келесі жылдың басында жоспарланған) стандартқа ауыстырылды. C++ 17.

Көшіруден кейін әзірлеушілерде көбірек опциялар болады. Егер бұрын бізде STL-дің өзгертілген нұсқасы және бір std аттар кеңістігі болса, енді бізде std аттар кеңістігінде, stdx аттар кеңістігінде кіріктірілген компилятор кітапханаларынан стандартты сыныптар бар - біздің тапсырмаларымыз үшін оңтайландырылған желілеріміз бен контейнерлеріміз, күшейтілген түрде - Boost соңғы нұсқасы. Ал әзірлеуші ​​өз мәселелерін шешу үшін оңтайлы сәйкес келетін сыныптарды пайдаланады.

Қозғалыс конструкторларының «туған» іске асырылуы да дамуға көмектеседі (конструкторларды жылжытыңыз) бірқатар сыныптар үшін. Егер сыныпта жылжыту конструкторы болса және бұл класс контейнерге орналастырылса, онда STL контейнер ішіндегі элементтерді көшіруді оңтайландырады (мысалы, контейнер кеңейтілгенде және сыйымдылықты өзгерту және жадты қайта бөлу қажет болғанда).

Майға құйыңыз

Көші-қонның ең жағымсыз (бірақ маңызды емес) салдары - біз көлемнің ұлғаюына тап болуымыз мүмкін. obj файлдары, және барлық аралық файлдармен құрастырудың толық нәтижесі 60–70 ГБ ала бастады. Бұл әрекет қазіргі стандартты кітапханалардың ерекшеліктеріне байланысты, олар жасалған сервистік файлдардың өлшеміне сыни тұрғыдан азырақ болды. Бұл құрастырылған қосымшаның жұмысына әсер етпейді, бірақ әзірлеуде бірқатар қолайсыздықтар тудырады, атап айтқанда, компиляция уақытын арттырады. Құрастыру серверлерінде және әзірлеушілер машиналарында бос дискілік кеңістікке қойылатын талаптар да артып келеді. Біздің әзірлеушілер платформаның бірнеше нұсқаларында қатар жұмыс істейді, ал аралық файлдардың жүздеген гигабайттары кейде олардың жұмысында қиындықтар тудырады. Мәселе жағымсыз, бірақ маңызды емес, біз оны шешуді әзірге кейінге қалдырдық. Біз оны шешудің бір нұсқасы ретінде технологияны қарастырамыз бірлік құру (атап айтқанда, Google оны Chrome браузерін жасау кезінде пайдаланады).

Ақпарат көзі: www.habr.com

пікір қалдыру