Qanday qilib biz 10 million satr C++ kodini C++14 standartiga (va keyin C++17 ga) tarjima qildik.

Bir muncha vaqt oldin (2016 yil kuzida) 1C: Enterprise texnologik platformasining navbatdagi versiyasini ishlab chiqish paytida, ishlab chiqish guruhida yangi standartni qo'llab-quvvatlash haqida savol paydo bo'ldi. C ++ 14 bizning kodimizda. Yangi standartga o'tish, biz taxmin qilganimizdek, ko'p narsalarni yanada oqlangan, sodda va ishonchli yozishga imkon beradi va kodni qo'llab-quvvatlash va texnik xizmat ko'rsatishni soddalashtiradi. Kod bazasining miqyosi va kodimizning o'ziga xos xususiyatlari bo'lmasa, tarjimada g'ayrioddiy narsa yo'qdek tuyuladi.

Bilmaganlar uchun, 1C: Enterprise - bu turli xil OT va ma'lumotlar bazalarida ishlash uchun platformalararo biznes ilovalarini va ish vaqtini jadal rivojlantirish uchun muhit. Umuman olganda, mahsulot tarkibiga quyidagilar kiradi:

  • Ilova serverlari klasteri, Windows va Linuxda ishlaydi
  • Xaridor, http(lar) yoki o'zining ikkilik protokoli orqali server bilan ishlash, Windows, Linux, macOS da ishlaydi
  • Veb mijoz, Chrome, Internet Explorer, Microsoft Edge, Firefox, Safari brauzerlarida ishlaydi (JavaScript-da yozilgan)
  • Rivojlanish muhiti (Konfigurator), Windows, Linux, macOS da ishlaydi
  • Boshqaruv vositalari Windows, Linux, macOS da ishlaydigan dastur serverlari
  • Mobil mijoz, http(lar) orqali serverga ulanish Android, iOS, Windows operatsion tizimlarida ishlaydigan mobil qurilmalarda ishlaydi
  • Mobil platforma β€” Android, iOS, Windows tizimlarida ishlaydigan sinxronlash imkoniyatiga ega bo'lgan oflayn mobil ilovalarni yaratish uchun asos
  • Rivojlanish muhiti 1C: Korxonani rivojlantirish vositalari, Java tilida yozilgan
  • Server O'zaro ta'sir tizimlari

Biz imkon qadar turli xil operatsion tizimlar uchun bir xil kodni yozishga harakat qilamiz - server kodlari bazasi 99% keng tarqalgan, mijoz kodlari bazasi taxminan 95% ni tashkil qiladi. 1C: Enterprise texnologiya platformasi asosan C++ tilida yozilgan va taxminiy kod tavsiflari quyida keltirilgan:

  • 10 million satr C++ kodi,
  • 14 ming fayl,
  • 60 ming sinf,
  • yarim million usul.

Va bularning barchasi C++ 14 ga tarjima qilinishi kerak edi. Bugun biz buni qanday qilganimizni va jarayonda nimalarga duch kelganimizni aytib beramiz.

Qanday qilib biz 10 million satr C++ kodini C++14 standartiga (va keyin C++17 ga) tarjima qildik.

Rad etish

Turli kutubxonalarda standart sinflarni qo'llash orqali sekin/tezkor ishlash, (emas) katta xotira iste'moli haqida quyida yozilganlarning hammasi bir narsani anglatadi: bu BIZ UCHUN to'g'ri. Standart ilovalar sizning vazifalaringizga eng mos kelishi mumkin. Biz o'z vazifalarimizdan boshladik: biz mijozlarimiz uchun odatiy bo'lgan ma'lumotlarni oldik, ular bo'yicha odatiy stsenariylarni ishga tushirdik, unumdorlik, iste'mol qilingan xotira miqdori va hokazolarni ko'rib chiqdik va biz va mijozlarimiz bunday natijalardan qoniqdimi yoki yo'qligini tahlil qildik. . Va ular qarab harakat qilishdi.

Bizda nima bor edi

Dastlab biz Microsoft Visual Studio'da 1C: Enterprise 8 platformasi kodini yozdik. Loyiha 2000-yillarning boshida boshlangan va bizda faqat Windows versiyasi mavjud edi. Tabiiyki, o'shandan beri kod faol ishlab chiqildi, ko'plab mexanizmlar butunlay qayta yozildi. Ammo kod 1998 yil standartiga muvofiq yozilgan va, masalan, kompilyatsiya muvaffaqiyatli bo'lishi uchun bizning to'g'ri burchakli qavslarimiz bo'shliqlar bilan ajratilgan, masalan:

vector<vector<int> > IntV;

2006 yilda platformaning 8.1 versiyasi chiqarilishi bilan biz Linuxni qo'llab-quvvatlay boshladik va uchinchi tomon standart kutubxonasiga o'tdik. STLPort. O'tishning sabablaridan biri keng chiziqlar bilan ishlash edi. Bizning kodimizda wchar_t turiga asoslangan std::wstring dan foydalanamiz. Windowsda uning hajmi 2 bayt, Linuxda esa sukut bo'yicha 4 bayt. Bu mijoz va server o'rtasidagi ikkilik protokollarimizning mos kelmasligiga, shuningdek, turli xil doimiy ma'lumotlarga olib keldi. Gcc parametrlaridan foydalanib, kompilyatsiya paytida wchar_t hajmi ham 2 bayt ekanligini belgilashingiz mumkin, ammo keyin siz kompilyatordan standart kutubxonadan foydalanishni unutishingiz mumkin, chunki u o'z navbatida 4 baytlik wchar_t uchun kompilyatsiya qilingan glibc dan foydalanadi. Boshqa sabablar standart sinflarni yaxshiroq amalga oshirish, xesh-jadvallarni qo'llab-quvvatlash va hatto biz faol foydalangan konteynerlar ichida harakatlanish semantikasini taqlid qilish edi. Va yana bir sabab, ular aytganidek, oxirgi, lekin eng muhimi, string ijrosi edi. Bizning torlar bo'yicha o'z sinfimiz bor edi, chunki ... Bizning dasturiy ta'minotimizning o'ziga xos xususiyatlaridan kelib chiqqan holda, string operatsiyalari juda keng qo'llaniladi va biz uchun bu juda muhim.

Bizning satrimiz 2000-yillarning boshlarida ifodalangan string optimallashtirish g'oyalariga asoslangan Andrey Aleksandresku. Keyinchalik, Aleksandresku Facebookda ishlaganida, uning taklifiga ko'ra, Facebook dvigatelida shunga o'xshash printsiplarda ishlaydigan chiziq ishlatilgan (qarang: kutubxona ahmoqlik).

Bizning liniyamiz ikkita asosiy optimallashtirish texnologiyasidan foydalangan:

  1. Qisqa qiymatlar uchun satr ob'ektidagi ichki bufer ishlatiladi (qo'shimcha xotira ajratishni talab qilmaydi).
  2. Qolganlarning hammasi uchun mexanika ishlatiladi Yozuvga nusxalash. Satr qiymati bir joyda saqlanadi va tayinlash/o'zgartirish vaqtida mos yozuvlar hisoblagichidan foydalaniladi.

Platformani kompilyatsiya qilishni tezlashtirish uchun biz STLPort variantimizdan (biz foydalanmagan) oqimni amalga oshirishni chiqarib tashladik, bu bizga taxminan 20% tezroq kompilyatsiya berdi. Keyinchalik biz cheklangan foydalanishga majbur bo'ldik kuchayish. Boost oqimdan, xususan, xizmat APIlarida (masalan, jurnalga yozish uchun) qattiq foydalanadi, shuning uchun biz oqimdan foydalanishni olib tashlash uchun uni o'zgartirishga majbur bo'ldik. Bu, o'z navbatida, Boostning yangi versiyalariga o'tishimizni qiyinlashtirdi.

Uchinchi yo'l

C++ 14 standartiga o'tishda biz quyidagi variantlarni ko'rib chiqdik:

  1. Biz o'zgartirgan STLPort-ni C++ 14 standartiga yangilang. Variant juda qiyin, chunki... STLPort-ni qo'llab-quvvatlash 2010 yilda to'xtatildi va biz uning barcha kodlarini o'zimiz yaratishimiz kerak edi.
  2. C++ 14 bilan mos keluvchi boshqa STL ilovasiga o'tish. Ushbu dastur Windows va Linux uchun bo'lishi juda ma'qul.
  3. Har bir OT uchun kompilyatsiya qilishda tegishli kompilyatorga o'rnatilgan kutubxonadan foydalaning.

Birinchi variant juda ko'p ish tufayli to'g'ridan-to'g'ri rad etildi.

Biz bir muncha vaqt ikkinchi variant haqida o'yladik; nomzod sifatida qaraladi libc++, lekin o'sha paytda u Windows ostida ishlamadi. libc++-ni Windows-ga o'tkazish uchun siz juda ko'p ish qilishingiz kerak bo'ladi - masalan, iplar, ip sinxronizatsiyasi va atomiklik bilan bog'liq bo'lgan hamma narsani o'zingiz yozing, chunki bu sohalarda libc++ ishlatiladi. POSIX API.

Va biz uchinchi yo'lni tanladik.

O'tish

Shunday qilib, biz STLPort-dan foydalanishni tegishli kompilyatorlarning kutubxonalari bilan almashtirishga majbur bo'ldik (Windows uchun Visual Studio 2015, Linux uchun gcc 7, macOS uchun clang 8).

Yaxshiyamki, bizning kodimiz asosan ko'rsatmalarga muvofiq yozilgan va har qanday aqlli fokuslardan foydalanmagan, shuning uchun turlar, sinflar, nomlar bo'shliqlari nomlarini almashtirgan va manbaga kiritilgan skriptlar yordamida yangi kutubxonalarga o'tish nisbatan muammosiz davom etdi. fayllar. Migratsiya 10 000 ta manba faylga ta'sir qildi (14 000 tadan). wchar_t char16_t bilan almashtirildi; biz wchar_t dan foydalanishdan voz kechishga qaror qildik, chunki char16_t barcha operatsion tizimlarda 2 baytni oladi va Windows va Linux o'rtasidagi kod mosligini buzmaydi.

Kichik sarguzashtlar bor edi. Misol uchun, STLPort-da iterator bilvosita elementga ko'rsatgichga o'tkazilishi mumkin va bizning kodimizning ba'zi joylarida bu ishlatilgan. Yangi kutubxonalarda buni qilishning iloji yo'q edi va bu parchalarni qo'lda tahlil qilish va qayta yozish kerak edi.

Shunday qilib, kod migratsiyasi tugallandi, kod barcha operatsion tizimlar uchun tuzilgan. Sinovlar vaqti keldi.

O'tishdan keyingi testlar kodning eski versiyasiga nisbatan ishlashning pasayishini (ba'zi joylarda 20-30% gacha) va xotira iste'molini (10-15% gacha) ko'rsatdi. Bu, xususan, standart satrlarning suboptimal ishlashi bilan bog'liq edi. Shuning uchun biz yana o'zimizning, biroz o'zgartirilgan chiziqdan foydalanishga majbur bo'ldik.

O'rnatilgan kutubxonalarda konteynerlarni amalga oshirishning qiziqarli xususiyati ham aniqlandi: o'rnatilgan kutubxonalardan bo'sh (elementlarsiz) std::map va std::set xotirani ajratadi. Amalga oshirish xususiyatlari tufayli kodning ba'zi joylarida ushbu turdagi juda ko'p bo'sh konteynerlar yaratilgan. Standart xotira konteynerlari bitta ildiz elementi uchun ozgina ajratilgan, ammo biz uchun bu juda muhim bo'lib chiqdi - bir qator stsenariylarda ishlashimiz sezilarli darajada pasaydi va xotira iste'moli oshdi (STLPort bilan solishtirganda). Shuning uchun, bizning kodimizda biz ushbu ikki turdagi konteynerlarni o'rnatilgan kutubxonalardan Boost-dan amalga oshirish bilan almashtirdik, bu erda bu konteynerlarda bunday xususiyat yo'q edi va bu sekinlashuv va xotira sarfini oshirish muammosini hal qildi.

Katta loyihalardagi keng ko'lamli o'zgarishlardan so'ng tez-tez sodir bo'lganidek, dastlabki kodning birinchi iteratsiyasi muammosiz ishlamadi va bu erda, xususan, Windows-ni amalga oshirishda iteratorlarni disk raskadrovka qilishni qo'llab-quvvatlash foydali bo'ldi. Biz bosqichma-bosqich oldinga siljidik va 2017 yil bahoriga kelib (8.3.11 1C: Enterprise versiyasi) migratsiya yakunlandi.

natijalar

C++ 14 standartiga o'tish bizga taxminan 6 oy davom etdi. Ko'pincha loyihada bitta (lekin juda yuqori malakali) ishlab chiquvchi ishladi va yakuniy bosqichda ma'lum sohalar uchun mas'ul bo'lgan jamoalar vakillari qo'shildi - UI, server klasteri, ishlab chiqish va boshqarish vositalari va boshqalar.

O'tish standartning so'nggi versiyalariga o'tish bo'yicha ishimizni ancha soddalashtirdi. Shunday qilib, 1C: Enterprise 8.3.14 versiyasi (ishlab chiqishda, chiqarilishi keyingi yilning boshida) allaqachon standartga o'tkazildi C++ 17.

Migratsiyadan so'ng, ishlab chiquvchilar ko'proq imkoniyatlarga ega. Agar ilgari bizda STL ning o'zgartirilgan versiyasi va bitta std nom maydoni bo'lgan bo'lsa, endi bizda std nomlar maydonida, stdx nomlar maydonida o'rnatilgan kompilyator kutubxonalaridan standart sinflar mavjud - bizning vazifalarimiz uchun optimallashtirilgan chiziqlarimiz va konteynerlarimiz, kuchaytirilganda - Boost so'nggi versiyasi. Va ishlab chiquvchi o'z muammolarini hal qilish uchun eng mos bo'lgan sinflardan foydalanadi.

Harakat konstruktorlarining "mahalliy" amalga oshirilishi ham rivojlanishga yordam beradi (konstruktorlarni ko'chirish) bir qator sinflar uchun. Agar sinfda ko'chirish konstruktori bo'lsa va bu sinf konteynerga joylashtirilgan bo'lsa, u holda STL konteyner ichidagi elementlarni nusxalashni optimallashtiradi (masalan, konteyner kengaytirilganda va sig'imni o'zgartirish va xotirani qayta taqsimlash kerak bo'lganda).

Bir qoshiq tar

Ehtimol, migratsiyaning eng yoqimsiz (lekin muhim bo'lmagan) oqibati shundaki, biz hajmning oshishiga duch kelamiz. obj fayllari, va barcha oraliq fayllar bilan qurishning to'liq natijasi 60-70 Gb ni egallay boshladi. Ushbu xatti-harakatlar zamonaviy standart kutubxonalarning o'ziga xos xususiyatlari bilan bog'liq bo'lib, ular yaratilgan xizmat fayllari hajmiga nisbatan kamroq tanqidiy munosabatda bo'lib qoldi. Bu kompilyatsiya qilingan ilovaning ishlashiga ta'sir qilmaydi, lekin u ishlab chiqishda bir qator noqulayliklarni keltirib chiqaradi, xususan, kompilyatsiya vaqtini oshiradi. Qurilish serverlarida va ishlab chiquvchi mashinalarda bo'sh disk maydoniga talablar ham ortib bormoqda. Ishlab chiquvchilarimiz platformaning bir nechta versiyalarida parallel ravishda ishlaydi va yuzlab gigabayt oraliq fayllar ba'zan ularning ishlarida qiyinchiliklar tug'diradi. Muammo yoqimsiz, ammo muhim emas, biz uni hal qilishni hozircha qoldirdik. Biz texnologiyani uni hal qilish variantlaridan biri sifatida ko'rib chiqamiz birlikni shakllantirish (xususan, Google Chrome brauzerini ishlab chiqishda undan foydalanadi).

Manba: www.habr.com

a Izoh qo'shish