{"id":32466,"date":"2019-10-31T21:47:13","date_gmt":"2019-10-31T18:47:13","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17\/"},"modified":"2019-10-31T21:47:13","modified_gmt":"2019-10-31T18:47:13","slug":"kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","title":{"rendered":"Jak przet\u0142umaczyli\u015bmy 10 milion\u00f3w linii kodu C++ na standard C++14 (a potem na C++17)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Jaki\u015b czas temu (jesieni\u0105 2016 roku), podczas prac nad now\u0105 wersj\u0105 platformy technologicznej 1C:Enterprise w zespole deweloperskim pojawi\u0142o si\u0119 pytanie o wsparcie nowego standardu <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/C%2B%2B14\">C++14<\/a><\/noindex> w naszym kodzie. Przej\u015bcie na nowy standard, jak zak\u0142adali\u015bmy, pozwoli\u0142oby nam pisa\u0107 wiele rzeczy elegancko, prosto i niezawodnie, upro\u015bci\u0142oby wsparcie i utrzymanie kodu. I w t\u0142umaczeniu nie ma nic nadzwyczajnego, gdyby nie rozmiar bazy kodu i specyficzne cechy naszego kodu.<\/p>\n<p>Dla tych, kt\u00f3rzy nie wiedz\u0105, 1C:Enterprise to \u015brodowisko do szybkiego rozwoju aplikacji biznesowych na r\u00f3\u017cnych platformach i czas wykonywania ich w r\u00f3\u017cnych systemach operacyjnych i bazach danych. W skr\u00f3cie, sk\u0142ad produktu obejmuje:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000885.htm\">Klaster serwer\u00f3w aplikacji<\/a><\/noindex>, dzia\u0142aj\u0105cy na Windows i Linux<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000124.htm\">Klient<\/a><\/noindex>, kt\u00f3ry \u0142\u0105czy si\u0119 z serwerem przez http(s) lub w\u0142asny protok\u00f3\u0142 binarny, dzia\u0142a na Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/315414\/\">Klient internetowy<\/a><\/noindex>, dzia\u0142aj\u0105cy w przegl\u0105darkach Chrome, Internet Explorer, Microsoft Edge, Firefox, Safari (napisany w JavaScript)<\/li>\n<li>\u015arodowisko programistyczne (<noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000008.htm\">Konfigurator<\/a><\/noindex>), dzia\u0142aj\u0105ce na Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000813.htm\">Narz\u0119dzia administracyjne<\/a><\/noindex> serwer\u00f3w aplikacji, dzia\u0142aj\u0105 na Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/wonderland.v8.1c.ru\/blog\/mobilnyy-klient\/\">Klient mobilny<\/a><\/noindex>, \u0142\u0105cz\u0105cy si\u0119 z serwerem przez http(s), dzia\u0142a na urz\u0105dzeniach mobilnych z systemem Android, iOS, Windows<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/283198\/\">Platforma mobilna<\/a><\/noindex> \u2014 framework do tworzenia offline'owych aplikacji mobilnych z mo\u017cliwo\u015bci\u0105 synchronizacji, dzia\u0142aj\u0105cych na Android, iOS, Windows<\/li>\n<li>\u015arodowisko deweloperskie <noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/IDE\/\">1C:Enterprise Development Tools<\/a><\/noindex>, napisana w Java<\/li>\n<li>Serwer <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/422903\/\">Systemy Interakcji<\/a><\/noindex><\/li>\n<\/ul>\n<p>\nStarali\u015bmy si\u0119 pisa\u0107 jeden kod na r\u00f3\u017cne systemy operacyjne \u2014 baza kodu serwera jest wsp\u00f3lna w 99%, klienta \u2014 w oko\u0142o 95%. Platforma technologiczna 1C:Enterprise jest w przewa\u017caj\u0105cej mierze napisana w C++ i poni\u017cej przedstawiamy przybli\u017cone charakterystyki kodu:<\/p>\n<ul>\n<li>10 milion\u00f3w lini kodu C++,<\/li>\n<li>14 tysi\u0119cy plik\u00f3w,<\/li>\n<li>60 tysi\u0119cy klas,<\/li>\n<li>p\u00f3\u0142 miliona metod.<\/li>\n<\/ul>\n<p>\nI to wszystko trzeba by\u0142o przenie\u015b\u0107 na C++14. O tym, jak to zrobili\u015bmy i z czym si\u0119 zmierzyli\u015bmy w trakcie, opowiemy dzisiaj.<\/p>\n<p><img decoding=\"async\" alt=\"Jak przet\u0142umaczyli\u015bmy 10 milion\u00f3w linii kodu C++ na standard C++14 (a potem na C++17)\" src=\"\/wp-content\/uploads\/2019\/04\/7f9270bc37fa9fd462ac9efbb12f0764.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Wy\u0142\u0105czenie odpowiedzialno\u015bci<\/h3>\n<p>\nWszystko, co napisano poni\u017cej na temat powolnej\/szybkiej pracy, (nie) du\u017cego zu\u017cycia pami\u0119ci implementacjami standardowych klas w r\u00f3\u017cnych bibliotekach, oznacza jedno: jest to prawda DLA NAS. Mo\u017cliwe, \u017ce dla Twoich zada\u0144 standardowe implementacje b\u0119d\u0105 najlepsze. My jednak opierali\u015bmy si\u0119 na swoich potrzebach: brali\u015bmy typowe dla naszych klient\u00f3w dane, uruchamiali\u015bmy na nich typowe scenariusze, analizowali\u015bmy wydajno\u015b\u0107, zu\u017cycie pami\u0119ci itd., i oceniali\u015bmy \u2013 czy takie wyniki s\u0105 dla nas i naszych klient\u00f3w satysfakcjonuj\u0105ce, czy nie. I post\u0119powali\u015bmy w zale\u017cno\u015bci od tego.<\/p>\n<h3>Co mieli\u015bmy<\/h3>\n<p>\nPocz\u0105tkowo pisali\u015bmy kod platformy 1C: Przedsi\u0119biorstwo 8 w Microsoft Visual Studio. Projekt rozpocz\u0105\u0142 si\u0119 na pocz\u0105tku lat 2000-tych i mieli\u015bmy tylko wersj\u0119 na Windows. Naturalnie, od tego czasu kod intensywnie ewoluowa\u0142, wiele mechanizm\u00f3w zosta\u0142o ca\u0142kowicie przepisanych. Ale kod by\u0142 pisany zgodnie z norm\u0105 z 1998 roku, a na przyk\u0142ad prawe nawiasy by\u0142y oddzielone spacjami, aby kompilacja przesz\u0142a pomy\u015blnie, tak:<\/p>\n<pre><code class=\"cpp\">vector&lt;vector &gt; IntV;<\/code><\/pre>\n<p>\nW 2006 roku, z wydaniem wersji platformy 8.1, zacz\u0119li\u015bmy wspiera\u0107 Linux i przeszli\u015bmy na zewn\u0119trzn\u0105 standardow\u0105 bibliotek\u0119 <noindex><a rel=\"nofollow\" href=\"http:\/\/www.stlport.org\/\">STLPort<\/a><\/noindex>. Jednym z powod\u00f3w przej\u015bcia by\u0142a obs\u0142uga szerokich \u0142a\u0144cuch\u00f3w. W naszym kodzie powszechnie u\u017cywamy std::wstring, opartego na typie wchar_t. Jego rozmiar w Windows wynosi 2 bajty, a w Linuxie domy\u015blnie 4 bajty. Prowadzi\u0142o to do niekompatybilno\u015bci naszych protoko\u0142\u00f3w binarnych mi\u0119dzy klientem a serwerem, a tak\u017ce r\u00f3\u017cnych danych trwa\u0142ych. Opcjami gcc mo\u017cna wskaza\u0107, aby rozmiar wchar_t podczas kompilacji wynosi\u0142 te\u017c 2 bajty, ale wtedy mo\u017cna zapomnie\u0107 o u\u017cywaniu standardowej biblioteki od kompilatora, poniewa\u017c korzysta ona z glibc, kt\u00f3ra z kolei zosta\u0142a skompilowana pod 4-bajtowy wchar_t. Innymi powodami by\u0142y lepsze implementacje standardowych klas, wsparcie dla tablic mieszaj\u0105cych, a nawet emulacja semantyki przenoszenia wewn\u0105trz kontener\u00f3w, z kt\u00f3rej aktywnie korzystali\u015bmy. A jeszcze jednym powodem, \u017ce tak powiem, ostatnim, ale nie mniej wa\u017cnym, by\u0142a wydajno\u015b\u0107 \u0142a\u0144cuch\u00f3w. Mieli\u015bmy swoj\u0105 klas\u0119 dla \u0142a\u0144cuch\u00f3w, poniewa\u017c w zwi\u0105zku z charakterystyk\u0105 naszego oprogramowania operacje na \u0142a\u0144cuchach s\u0105 stosowane bardzo szeroko i s\u0105 dla nas krytyczne. <\/p>\n<p>Nasz \u0142a\u0144cuch oparty jest na pomys\u0142ach optymalizacji \u0142a\u0144cuch\u00f3w, wyra\u017conych jeszcze na pocz\u0105tku lat 2000-tych <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B5%D1%81%D0%BA%D1%83,_%D0%90%D0%BD%D0%B4%D1%80%D0%B5%D0%B9\">Andrieja Alexandrescu<\/a><\/noindex>. P\u00f3\u017aniej, gdy Alexandrescu pracowa\u0142 w Facebooku, na jego wniosek w silniku Facebooka zastosowano ci\u0105g dzia\u0142aj\u0105cy na podobnych zasadach (zob. biblioteka <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/folly\">folly<\/a><\/noindex>).<\/p>\n<p>W naszym ci\u0105gu u\u017cyto dw\u00f3ch g\u0142\u00f3wnych technologii optymalizacji:<\/p>\n<ol>\n<li>Dla kr\u00f3tkich warto\u015bci u\u017cywany jest wewn\u0119trzny bufor w samym obiekcie ci\u0105gu (nie wymagaj\u0105cy dodatkowej alokacji pami\u0119ci).<\/li>\n<li>Dla wszystkich pozosta\u0142ych u\u017cywa si\u0119 mechaniki <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8\">Copy On Write<\/a><\/noindex>. Warto\u015b\u0107 ci\u0105gu jest przechowywana w jednym miejscu, przy przypisaniu\/modyfikacji u\u017cywany jest licznik odwo\u0142a\u0144.<\/li>\n<\/ol>\n<p>\nAby przyspieszy\u0107 kompilacj\u0119 platformy, wykluczyli\u015bmy z naszej wersji STLPort implementacj\u0119 stream (kt\u00f3rej nie u\u017cywali\u015bmy), co da\u0142o nam przyspieszenie kompilacji o oko\u0142o 20%. P\u00f3\u017aniej musieli\u015bmy ograniczy\u0107 korzystanie z <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Boost\">Boost<\/a><\/noindex>. Boost aktywnie u\u017cywa stream, w szczeg\u00f3lno\u015bci w swoich API us\u0142ugowych (np. do logowania), dlatego musieli\u015bmy go zmodyfikowa\u0107, wykluczaj\u0105c z niego u\u017cycie stream. To z kolei utrudnia\u0142o nam przej\u015bcie na nowsze wersje Boost. <\/p>\n<h3>Trzeci spos\u00f3b<\/h3>\n<p>\nPrzy przej\u015bciu na standard C++14 rozwa\u017cali\u015bmy takie opcje:<\/p>\n<ol>\n<li>Podnie\u015b\u0107 zmodyfikowany przez nas STLPort do standardu C++14. Opcja ta jest bardzo skomplikowana, poniewa\u017c wsparcie dla STLPortu zosta\u0142o zaprzestane w 2010 roku, a podniesienie ca\u0142ego jego kodu musieliby\u015bmy wykona\u0107 samodzielnie.<\/li>\n<li>Przej\u015bcie na inn\u0105 implementacj\u0119 STL, kompatybiln\u0105 z C++14. Niezb\u0119dne jest, aby ta implementacja dzia\u0142a\u0142a zar\u00f3wno na Windows, jak i Linux.<\/li>\n<li>U\u017cycie w kompilacji wbudowanej w odpowiedni kompilator biblioteki dla ka\u017cdego systemu operacyjnego.<\/li>\n<\/ol>\n<p>\nPierwsza opcja zosta\u0142a odrzucona od razu z powodu zbyt du\u017cego zakresu pracy.<\/p>\n<p>Przez jaki\u015b czas rozwa\u017cali\u015bmy drug\u0105 opcj\u0119; jako kandydata brali\u015bmy pod uwag\u0119 <noindex><a rel=\"nofollow\" href=\"https:\/\/libcxx.llvm.org\/\">libc++<\/a><\/noindex>, ale w tamtym czasie nie dzia\u0142a\u0142 pod Windows. Aby przenie\u015b\u0107 libc++ na Windows, trzeba by by\u0142o wykona\u0107 wiele pracy \u2014 na przyk\u0142ad napisa\u0107 samodzielnie wszystko, co zwi\u0105zane z w\u0105tkami, synchronizacj\u0105 w\u0105tk\u00f3w i atomowo\u015bci\u0105, poniewa\u017c w libc++ w tych obszarach u\u017cywano <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/POSIX\">POSIX API<\/a><\/noindex>.<\/p>\n<p>I wybrali\u015bmy trzeci spos\u00f3b.<\/p>\n<h3>Przej\u015bcie<\/h3>\n<p>\nTak wi\u0119c musieli\u015bmy zast\u0105pi\u0107 u\u017cycie STLPort bibliotekami odpowiednich kompilator\u00f3w (Visual Studio 2015 dla Windows, gcc 7 dla Linux, clang 8 dla macOS). <\/p>\n<p>Na szcz\u0119\u015bcie nasz kod by\u0142 pisany g\u0142\u00f3wnie wed\u0142ug wytycznych i nie u\u017cywa\u0142 r\u00f3\u017cnych trik\u00f3w, wi\u0119c migracja na nowe biblioteki przebieg\u0142a stosunkowo g\u0142adko, za pomoc\u0105 skrypt\u00f3w, kt\u00f3re zast\u0119powa\u0142y w \u017ar\u00f3d\u0142owych plikach nazwy typ\u00f3w, klas, przestrzeni nazw i do\u0142\u0105cze\u0144. Migracja obj\u0119\u0142a 10 000 \u017ar\u00f3d\u0142owych plik\u00f3w (z 14 000). wchar_t zosta\u0142 zast\u0105piony przez char16_t; postanowili\u015bmy zrezygnowa\u0107 z u\u017cycia wchar_t, poniewa\u017c char16_t zajmuje 2 bajty we wszystkich systemach operacyjnych i nie psuje kompatybilno\u015bci kodu mi\u0119dzy Windows a Linux.<\/p>\n<p>Nie oby\u0142o si\u0119 bez ma\u0142ych przyg\u00f3d. Na przyk\u0142ad w STLPort iterator mo\u017cna by\u0142o niejawnie rzutowa\u0107 na wska\u017anik do elementu, i w niekt\u00f3rych miejscach naszego kodu to wykorzystywano. W nowych bibliotekach nie by\u0142o to ju\u017c mo\u017cliwe, wi\u0119c te miejsca trzeba by\u0142o r\u0119cznie analizowa\u0107 i przepisywa\u0107. <\/p>\n<p>Tak wi\u0119c migracja kodu zosta\u0142a zako\u0144czona, kod jest kompilowany dla wszystkich system\u00f3w operacyjnych. Nadszed\u0142 czas na testy. <\/p>\n<p>Testy po przej\u015bciu pokaza\u0142y spadek wydajno\u015bci (miejscami o 20-30%) i wzrost zu\u017cycia pami\u0119ci (do 10-15%) w por\u00f3wnaniu ze star\u0105 wersj\u0105 kodu. By\u0142o to, w szczeg\u00f3lno\u015bci, zwi\u0105zane z nieoptymaln\u0105 prac\u0105 standardowych \u0142a\u0144cuch\u00f3w. Dlatego musieli\u015bmy znowu u\u017cy\u0107 w\u0142asnego \u0142a\u0144cucha, nieco zmodyfikowanego. <\/p>\n<p>Odkryto r\u00f3wnie\u017c interesuj\u0105c\u0105 cech\u0119 implementacji kontener\u00f3w w wbudowanych bibliotekach: puste (bez element\u00f3w) std::map i std::set z wbudowanych bibliotek alokuj\u0105 pami\u0119\u0107. A w naszym kodzie, z powodu specyfiki implementacji, tworzy si\u0119 w niekt\u00f3rych miejscach du\u017co pustych kontener\u00f3w tego typu. Standardowe kontenery alokuj\u0105 troch\u0119 pami\u0119ci, dla jednego elementu g\u0142\u00f3wnego, ale dla nas okaza\u0142o si\u0119 to krytyczne \u2013 w niekt\u00f3rych scenariuszach wydajno\u015b\u0107 wyra\u017anie spad\u0142a, a zu\u017cycie pami\u0119ci wzros\u0142o (w por\u00f3wnaniu ze STLPort). Dlatego zast\u0105pili\u015bmy w naszym kodzie te dwa typy kontener\u00f3w z wbudowanych bibliotek ich implementacj\u0105 od Boost, gdzie te kontenery nie mia\u0142y takiej cechy, co rozwi\u0105za\u0142o problem z op\u00f3\u017anieniem i zwi\u0119kszonym zu\u017cyciem pami\u0119ci.<\/p>\n<p>Jak cz\u0119sto bywa po du\u017cych zmianach w du\u017cych projektach, pierwsza iteracja \u017ar\u00f3de\u0142 nie dzia\u0142a\u0142a bez problem\u00f3w, i tu bardzo przyda\u0142a si\u0119, mi\u0119dzy innymi, obs\u0142uga iteracji debuguj\u0105cych w wersji Windows. Krok po kroku posuwali\u015bmy si\u0119 naprz\u00f3d i na wiosn\u0119 2017 (wersja 8.3.11 1C:Przedsi\u0119biorstwa) migracja zosta\u0142a zako\u0144czona. <\/p>\n<h3>Podsumowanie<\/h3>\n<p>\nPrzej\u015bcie na standard C++14 zaj\u0119\u0142o nam oko\u0142o 6 miesi\u0119cy. Wi\u0119ksz\u0105 cz\u0119\u015b\u0107 czasu nad projektem pracowa\u0142 jeden (ale bardzo wykwalifikowany) programista, a na etapie ko\u0144cowym do\u0142\u0105czyli przedstawiciele zespo\u0142\u00f3w odpowiedzialnych za konkretne obszary \u2014 UI, klaster serwer\u00f3w, narz\u0119dzia do tworzenia i administracji itd.<\/p>\n<p>Przej\u015bcie znacznie upro\u015bci\u0142o nam prac\u0119 nad migracj\u0105 do najnowszych wersji standardu. Tak, wersja 1C:Enterprise 8.3.14 (w opracowaniu, premiera zaplanowana na pocz\u0105tek przysz\u0142ego roku) zosta\u0142a ju\u017c przet\u0142umaczona na standard <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/C%2B%2B17\">C++17<\/a><\/noindex>. <\/p>\n<p>Po migracji programi\u015bci zyskali wi\u0119cej mo\u017cliwo\u015bci. Je\u015bli wcze\u015bniej mieli\u015bmy swoj\u0105 zmodyfikowan\u0105 wersj\u0119 STL i jedn\u0105 przestrze\u0144 nazw std, to teraz w przestrzeni nazw std znajduj\u0105 si\u0119 standardowe klasy z wbudowanych bibliotek kompilatora, w przestrzeni nazw stdx \u2013 nasze, zoptymalizowane dla naszych zada\u0144, \u0142a\u0144cuchy i kontenery, w boost \u2013 nowa wersja boost. I programista korzysta z tych klas, kt\u00f3re najlepiej pasuj\u0105 do rozwi\u0105zania jego zada\u0144. <\/p>\n<p>Pomaga w rozwoju r\u00f3wnie\u017c \u00abrodzima\u00bb implementacja konstruktor\u00f3w przenoszenia (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/move_constructor\">move constructors<\/a><\/noindex>) dla szeregu klas. Je\u015bli klasa ma konstruktor przenoszenia i ta klasa jest umieszczana w kontenerze, to STL optymalizuje kopiowanie element\u00f3w wewn\u0105trz kontenera (na przyk\u0142ad, gdy kontener si\u0119 rozszerza i trzeba zmieni\u0107 pojemno\u015b\u0107 i zrealokowa\u0107 pami\u0119\u0107). <\/p>\n<h3>\u0141y\u017cka dziegciu<\/h3>\n<p>\nNajbardziej, by\u0107 mo\u017ce, nieprzyjemnym (ale nie krytycznym) skutkiem migracji \u2014 napotkali\u015bmy zwi\u0119kszenie obj\u0119to\u015bci <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D1%8B%D0%B9_%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C\">plik\u00f3w obj<\/a><\/noindex>, a pe\u0142ny wynik kompilacji ze wszystkimi plikami po\u015brednimi zacz\u0105\u0142 zajmowa\u0107 po 60 \u2013 70 GB. Takie zachowanie zwi\u0105zane jest z cechami nowoczesnych standardowych bibliotek, kt\u00f3re zacz\u0119\u0142y mniej krytycznie podchodzi\u0107 do obj\u0119to\u015bci generowanych plik\u00f3w pomocniczych. To nie wp\u0142ywa na dzia\u0142anie skompilowanej aplikacji, ale sprawia szereg niedogodno\u015bci w programowaniu, w szczeg\u00f3lno\u015bci zwi\u0119ksza czas kompilacji. Wzrastaj\u0105 r\u00f3wnie\u017c wymagania co do wolnego miejsca na dysku na serwerach budowlanych i na maszynach programist\u00f3w. Nasi programi\u015bci r\u00f3wnolegle pracuj\u0105 nad kilkoma wersjami platformy, a setki gigabajt\u00f3w plik\u00f3w po\u015brednich czasami stwarzaj\u0105 trudno\u015bci w pracy. Problem jest nieprzyjemny, ale nie krytyczny, jego rozwi\u0105zanie na razie od\u0142o\u017cyli\u015bmy. Jako jeden z mo\u017cliwych sposob\u00f3w jego rozwi\u0105zania rozwa\u017camy technik\u0119 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Single_Compilation_Unit\">unity build<\/a><\/noindex> (mi\u0119dzy innymi, wykorzystuje to Google podczas opracowywania przegl\u0105darki Chrome).<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/1c\/blog\/429678\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 C++14 \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u043b\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0431\u044b \u043d\u0430\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u0432\u0435\u0449\u0438 \u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u0435\u0439, \u043f\u0440\u043e\u0449\u0435 \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u0435\u0439, \u0443\u043f\u0440\u043e\u0449\u0430\u043b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430. \u0418 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u0432\u0440\u043e\u0434\u0435 \u0431\u044b \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u044d\u043a\u0441\u0442\u0440\u0430\u043e\u0440\u0434\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24270,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32466","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u043b\u0438 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 C++ \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++14 (\u0430 \u043f\u043e\u0442\u043e\u043c \u0438 \u043d\u0430 C++17) | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:47:13+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:47:13+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Jak przet\u0142umaczyli\u015bmy 10 milion\u00f3w wierszy kodu C++ na standard C++14 (a potem na C++17) | ProHoster","description":"Jaki\u015b czas temu (jesieni\u0105 2016 roku), podczas prac nad now\u0105 wersj\u0105 platformy technologicznej 1C:Enterprise w zespole deweloperskim pojawi\u0142o si\u0119 pytanie o wsparcie nowego standardu","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u043b\u0438 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 C++ \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++14 (\u0430 \u043f\u043e\u0442\u043e\u043c \u0438 \u043d\u0430 C++17) | ProHoster","og:description":"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:47:13+00:00","article:modified_time":"2019-10-31T18:47:13+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32466","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 11:00:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:58:23","updated":"2026-01-21 11:00:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/32466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=32466"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/32466\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/24270"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=32466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=32466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=32466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}