Кантип биз 10 миллион сап C++ кодун C++14 стандартына (анан кийин C++17ге) котордук

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

Билбегендер үчүн 1С: Enterprise бул кросс-платформалык бизнес тиркемелерин тез өнүктүрүү үчүн чөйрө жана аларды ар кандай ОС жана DBMSтерде аткаруу үчүн иштөө убактысы. Жалпысынан алганда, продукт камтыйт:

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

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

Жана мунун баарын C++ 14 тилине которуу керек болчу. Бүгүн биз муну кантип жасаганыбызды жана процессте эмнеге туш болгонубузду айтып беребиз.

Кантип биз 10 миллион сап C++ кодун 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 кыймылдаткычында ушул сыяктуу принциптерде иштеген линия колдонулган (китепкананы караңыз). акылсыздык).

Биздин линия эки негизги оптималдаштыруу технологияларын колдонгон:

  1. Кыска маанилер үчүн сап объектинин өзүндөгү ички буфер колдонулат (кошумча эстутумду бөлүштүрүүнү талап кылбайт).
  2. Бардык башкалары үчүн механика колдонулат Жаз боюнча көчүрмө. Саптын мааниси бир жерде сакталат жана дайындоо/өзгөртүү учурунда шилтеме эсептегич колдонулат.

Платформанын компиляциясын тездетүү үчүн биз STLPort вариантыбыздан агымдын ишке ашырылышын чыгарып салдык (аны биз колдонгон эмес), бул бизге 20% тезирээк компиляция берди. Кийинчерээк биз чектелүү пайдаланууга туура келди кубаттоо. Boost агымды көп колдонот, айрыкча анын кызмат API'леринде (мисалы, журналды жазуу үчүн), ошондуктан агымдын колдонулушун алып салуу үчүн аны өзгөртүүгө туура келди. Бул, өз кезегинде, бизге Boostтун жаңы версияларына өтүүнү кыйындатты.

Үчүнчү жол

C++ 14 стандартына өтүүдө биз төмөнкү варианттарды карап чыктык:

  1. Биз C++ 14 стандартына өзгөрткөн STLPortти жаңыртыңыз. Вариант абдан кыйын, анткени... 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С: Enterprise) миграция аяктады.

натыйжалары

C++ 14 стандартына өтүү бизге 6 айга жакын убакытты алды. Көпчүлүк учурда долбоордо бир (бирок өтө квалификациялуу) иштеп чыгуучу иштеген, ал эми акыркы этапта конкреттүү чөйрөлөр үчүн жооптуу топтордун өкүлдөрү кошулган - UI, сервер кластери, иштеп чыгуу жана башкаруу куралдары ж.б.

Өткөөл стандарттын акыркы версияларына өтүү боюнча ишибизди бир топ жөнөкөйлөттү. Ошентип, 1С: Enterprise 8.3.14 версиясы (иштеп чыгууда, релиз келерки жылдын башына пландаштырылган) буга чейин стандартка которулган C++ 17.

Миграциядан кийин иштеп чыгуучулардын көбүрөөк мүмкүнчүлүктөрү бар. Эгерде мурда бизде STLдин өзгөртүлгөн версиясы жана бир std аталыш мейкиндиги болсо, азыр бизде std аттар мейкиндигинде, stdx аттар мейкиндигинде орнотулган компилятор китепканаларынан стандарттуу класстар бар - биздин тапшырмаларыбыз үчүн оптималдаштырылган сызыктарыбыз жана контейнерлерибиз, күчөтүлгөн режимде. Boost акыркы версиясы. Ал эми иштеп чыгуучу өз көйгөйлөрүн чечүү үчүн оптималдуу ылайыктуу класстарды колдонот.

Кыймыл конструкторлорунун "туган" ишке ашырылышы да өнүгүүгө жардам берет (конструкторлорду жылдыруу) бир катар класстар үчүн. Эгерде класста көчүрүү конструктору бар болсо жана бул класс контейнерге жайгаштырылса, анда STL контейнердин ичиндеги элементтерди көчүрүүнү оптималдаштырат (мисалы, контейнер кеңейтилгенде жана сыйымдуулукту өзгөртүү жана эстутумду кайра бөлүштүрүү зарыл болгондо).

Бир кашык чайыр

Миграциянын эң жагымсыз (бирок критикалык эмес) кесепети, балким, биз көлөмдүн көбөйүшүнө туш болуп жатабыз. obj файлдары, жана бардык орто файлдар менен куруунун толук натыйжасы 60-70 ГБ ээлей баштады. Мындай жүрүм-турум заманбап стандарттык китепканалардын өзгөчөлүгүнө байланыштуу, алар түзүлгөн сервистик файлдардын көлөмүнө анчалык критикалуу болуп калды. Бул компиляцияланган тиркеменин иштешине таасирин тийгизбейт, бирок иштеп чыгууда бир катар ыңгайсыздыктарды жаратат, атап айтканда, компиляция убактысын көбөйтөт. Куруучу серверлерде жана иштеп чыгуучу машиналарда бош диск мейкиндигине талаптар да көбөйүүдө. Биздин иштеп чыгуучулар платформанын бир нече версияларында параллелдүү иштешет жана жүздөгөн гигабайт аралык файлдар кээде алардын ишинде кыйынчылыктарды жаратат. Маселе жагымсыз, бирок критикалык эмес, биз аны чечүүнү азырынча кийинкиге калтырдык. Аны чечүүнүн варианттарынын бири катары технологияны карап жатабыз биримдикти куруу (айрыкча, Google аны Chrome браузерин иштеп чыгууда колдонот).

Source: www.habr.com

Комментарий кошуу