మేము 10 మిలియన్ లైన్ల C++ కోడ్‌ని C++14 స్టాండర్డ్‌కి (తర్వాత C++17కి) ఎలా అనువదించాము

కొంతకాలం క్రితం (2016 శరదృతువులో), 1C: Enterprise టెక్నాలజీ ప్లాట్‌ఫారమ్ యొక్క తదుపరి వెర్షన్ అభివృద్ధి సమయంలో, కొత్త ప్రమాణానికి మద్దతు ఇవ్వడం గురించి డెవలప్‌మెంట్ బృందంలో ప్రశ్న తలెత్తింది. C ++ 14 మా కోడ్‌లో. కొత్త ప్రమాణానికి మారడం, మేము ఊహించినట్లుగా, అనేక విషయాలను మరింత సొగసైన, సరళంగా మరియు విశ్వసనీయంగా వ్రాయడానికి అనుమతిస్తుంది మరియు కోడ్ యొక్క మద్దతు మరియు నిర్వహణను సులభతరం చేస్తుంది. మరియు కోడ్ బేస్ యొక్క స్కేల్ మరియు మా కోడ్ యొక్క నిర్దిష్ట లక్షణాల కోసం కాకపోతే, అనువాదంలో అసాధారణమైనది ఏమీ లేదు.

తెలియని వారికి, 1C:Enterprise అనేది క్రాస్-ప్లాట్‌ఫారమ్ బిజినెస్ అప్లికేషన్‌ల వేగవంతమైన అభివృద్ధి మరియు వివిధ OSలు మరియు DBMSలలో వాటి అమలు కోసం రన్‌టైమ్ కోసం ఒక పర్యావరణం. సాధారణ పరంగా, ఉత్పత్తి వీటిని కలిగి ఉంటుంది:

మేము వేర్వేరు ఆపరేటింగ్ సిస్టమ్‌ల కోసం ఒకే కోడ్‌ని వీలైనంత వరకు వ్రాయడానికి ప్రయత్నిస్తాము - సర్వర్ కోడ్ బేస్ 99% సాధారణం, క్లయింట్ కోడ్ బేస్ 95%. 1C:Enterprise టెక్నాలజీ ప్లాట్‌ఫారమ్ ప్రాథమికంగా C++లో వ్రాయబడింది మరియు సుమారు కోడ్ లక్షణాలు క్రింద ఇవ్వబడ్డాయి:

  • C++ కోడ్ యొక్క 10 మిలియన్ లైన్లు,
  • 14 వేల ఫైళ్లు,
  • 60 వేల తరగతులు,
  • అర మిలియన్ పద్ధతులు.

మరియు ఈ అంశాలన్నీ C++14లోకి అనువదించవలసి ఉంది. ఈ రోజు మనం దీన్ని ఎలా చేసాము మరియు ఈ ప్రక్రియలో మనం ఏమి ఎదుర్కొన్నామో తెలియజేస్తాము.

మేము 10 మిలియన్ లైన్ల C++ కోడ్‌ని C++14 స్టాండర్డ్‌కి (తర్వాత C++17కి) ఎలా అనువదించాము

నిరాకరణ

స్లో/ఫాస్ట్ వర్క్, (కాదు) వివిధ లైబ్రరీలలో స్టాండర్డ్ క్లాస్‌ల ఇంప్లిమెంటేషన్‌ల ద్వారా పెద్ద మెమరీ వినియోగం గురించి క్రింద వ్రాసిన ప్రతిదీ ఒక విషయం: ఇది US కోసం నిజం. మీ పనులకు ప్రామాణిక అమలులు ఉత్తమంగా సరిపోయే అవకాశం ఉంది. మేము మా స్వంత పనుల నుండి ప్రారంభించాము: మేము మా క్లయింట్‌లకు విలక్షణమైన డేటాను తీసుకున్నాము, వాటిపై విలక్షణమైన దృశ్యాలను అమలు చేసాము, పనితీరు, వినియోగించిన మెమరీ మొత్తం మొదలైనవాటిని పరిశీలించాము మరియు మేము మరియు మా క్లయింట్‌లు అటువంటి ఫలితాలతో సంతృప్తి చెందారా లేదా అని విశ్లేషించాము. . మరియు వారు ఆధారపడి నటించారు.

మన దగ్గర ఉన్నది

ప్రారంభంలో, మేము Microsoft Visual Studioలో 1C:Enterprise 8 ప్లాట్‌ఫారమ్ కోసం కోడ్‌ని వ్రాసాము. ప్రాజెక్ట్ 2000ల ప్రారంభంలో ప్రారంభమైంది మరియు మేము Windows-మాత్రమే సంస్కరణను కలిగి ఉన్నాము. సహజంగానే, అప్పటి నుండి కోడ్ చురుకుగా అభివృద్ధి చేయబడింది, అనేక యంత్రాంగాలు పూర్తిగా తిరిగి వ్రాయబడ్డాయి. కానీ కోడ్ 1998 ప్రమాణం ప్రకారం వ్రాయబడింది మరియు ఉదాహరణకు, మా లంబ కోణం బ్రాకెట్‌లు ఖాళీలతో వేరు చేయబడ్డాయి, తద్వారా సంకలనం విజయవంతమవుతుంది, ఇలా:

vector<vector<int> > IntV;

2006లో, ప్లాట్‌ఫారమ్ వెర్షన్ 8.1 విడుదలతో, మేము Linuxకి మద్దతు ఇవ్వడం ప్రారంభించాము మరియు మూడవ పక్షం ప్రామాణిక లైబ్రరీకి మారాము. STLపోర్ట్. విస్తృత పంక్తులతో పనిచేయడం పరివర్తనకు కారణాలలో ఒకటి. మా కోడ్‌లో, మేము std::wstringని ఉపయోగిస్తాము, ఇది అంతటా wchar_t రకంపై ఆధారపడి ఉంటుంది. Windowsలో దీని పరిమాణం 2 బైట్లు మరియు Linuxలో డిఫాల్ట్ 4 బైట్లు. ఇది క్లయింట్ మరియు సర్వర్ మధ్య మా బైనరీ ప్రోటోకాల్‌ల అననుకూలతకు దారితీసింది, అలాగే వివిధ నిరంతర డేటా. gcc ఎంపికలను ఉపయోగించి, కంపైలేషన్ సమయంలో wchar_t పరిమాణం కూడా 2 బైట్లు అని మీరు పేర్కొనవచ్చు, అయితే కంపైలర్ నుండి ప్రామాణిక లైబ్రరీని ఉపయోగించడం గురించి మీరు మరచిపోవచ్చు, ఎందుకంటే ఇది glibcని ఉపయోగిస్తుంది, ఇది 4-బైట్ wchar_t కోసం కంపైల్ చేయబడింది. ఇతర కారణాలు ప్రామాణిక తరగతులను మెరుగ్గా అమలు చేయడం, హాష్ టేబుల్‌లకు మద్దతు మరియు మేము చురుకుగా ఉపయోగించిన కంటైనర్‌ల లోపల కదిలే సెమాంటిక్స్ యొక్క ఎమ్యులేషన్. మరియు మరొక కారణం, వారు చివరిగా చెప్పినట్లు, స్ట్రింగ్ పనితీరు. మేము స్ట్రింగ్స్ కోసం మా స్వంత తరగతిని కలిగి ఉన్నాము, ఎందుకంటే... మా సాఫ్ట్‌వేర్ యొక్క ప్రత్యేకతల కారణంగా, స్ట్రింగ్ ఆపరేషన్‌లు చాలా విస్తృతంగా ఉపయోగించబడుతున్నాయి మరియు మాకు ఇది క్లిష్టమైనది.

మా స్ట్రింగ్ 2000ల ప్రారంభంలో వ్యక్తీకరించబడిన స్ట్రింగ్ ఆప్టిమైజేషన్ ఆలోచనలపై ఆధారపడింది ఆండ్రీ అలెగ్జాండ్రెస్కు. తరువాత, Alexandrescu Facebookలో పనిచేసినప్పుడు, అతని సూచన మేరకు, Facebook ఇంజిన్‌లో ఇలాంటి సూత్రాలపై పనిచేసే ఒక లైన్ ఉపయోగించబడింది (లైబ్రరీని చూడండి మూర్ఖత్వం).

మా లైన్ రెండు ప్రధాన ఆప్టిమైజేషన్ టెక్నాలజీలను ఉపయోగించింది:

  1. చిన్న విలువల కోసం, స్ట్రింగ్ ఆబ్జెక్ట్‌లోనే అంతర్గత బఫర్ ఉపయోగించబడుతుంది (అదనపు మెమరీ కేటాయింపు అవసరం లేదు).
  2. మిగతా వారందరికీ, మెకానిక్స్ ఉపయోగించబడుతుంది కాపీ ఆన్ రైట్. స్ట్రింగ్ విలువ ఒకే చోట నిల్వ చేయబడుతుంది మరియు అసైన్‌మెంట్/మార్పు సమయంలో రిఫరెన్స్ కౌంటర్ ఉపయోగించబడుతుంది.

ప్లాట్‌ఫారమ్ కంపైలేషన్‌ను వేగవంతం చేయడానికి, మేము మా STLPort వేరియంట్ నుండి స్ట్రీమ్ అమలును మినహాయించాము (దీనిని మేము ఉపయోగించలేదు), ఇది మాకు 20% వేగవంతమైన సంకలనాన్ని అందించింది. తదనంతరం మేము పరిమితంగా ఉపయోగించుకోవలసి వచ్చింది బూస్ట్. బూస్ట్ స్ట్రీమ్‌ను ఎక్కువగా ఉపయోగించుకుంటుంది, ప్రత్యేకించి దాని సేవా APIలలో (ఉదాహరణకు, లాగింగ్ కోసం), కాబట్టి మేము స్ట్రీమ్ వినియోగాన్ని తీసివేయడానికి దాన్ని సవరించాల్సి వచ్చింది. ఇది, బూస్ట్ యొక్క కొత్త వెర్షన్‌లకు మారడం మాకు కష్టతరం చేసింది.

మూడవ మార్గం

C++14 ప్రమాణానికి వెళ్లేటప్పుడు, మేము ఈ క్రింది ఎంపికలను పరిగణించాము:

  1. మేము C++14 ప్రమాణానికి సవరించిన STLPortని అప్‌గ్రేడ్ చేయండి. ఎంపిక చాలా కష్టం, ఎందుకంటే ... STLPort కోసం మద్దతు 2010లో నిలిపివేయబడింది మరియు దాని కోడ్ మొత్తాన్ని మనమే రూపొందించుకోవాలి.
  2. C++14కి అనుకూలమైన మరొక STL అమలుకు మార్పు. విండోస్ మరియు లైనక్స్ కోసం ఈ అమలు చేయడం చాలా అవసరం.
  3. ప్రతి OS కోసం కంపైల్ చేస్తున్నప్పుడు, సంబంధిత కంపైలర్‌లో నిర్మించిన లైబ్రరీని ఉపయోగించండి.

చాలా పని కారణంగా మొదటి ఎంపిక పూర్తిగా తిరస్కరించబడింది.

మేము కొంతకాలం రెండవ ఎంపిక గురించి ఆలోచించాము; అభ్యర్థిగా పరిగణించబడుతుంది libc++, కానీ ఆ సమయంలో అది Windows కింద పని చేయలేదు. Libc++ని Windowsకి పోర్ట్ చేయడానికి, మీరు చాలా పని చేయాల్సి ఉంటుంది - ఉదాహరణకు, థ్రెడ్‌లు, థ్రెడ్ సింక్రొనైజేషన్ మరియు అటామిసిటీకి సంబంధించిన ప్రతిదాన్ని మీరే వ్రాయండి, ఎందుకంటే ఈ ప్రాంతాల్లో libc++ ఉపయోగించబడింది. POSIX API.

మరియు మేము మూడవ మార్గాన్ని ఎంచుకున్నాము.

ట్రాన్సిషన్

కాబట్టి, మేము STLPort వినియోగాన్ని సంబంధిత కంపైలర్‌ల లైబ్రరీలతో భర్తీ చేయాల్సి వచ్చింది (Windows కోసం విజువల్ స్టూడియో 2015, Linux కోసం gcc 7, macOS కోసం క్లాంగ్ 8).

అదృష్టవశాత్తూ, మా కోడ్ ప్రధానంగా మార్గదర్శకాల ప్రకారం వ్రాయబడింది మరియు అన్ని రకాల తెలివైన ఉపాయాలను ఉపయోగించలేదు, కాబట్టి కొత్త లైబ్రరీలకు వలసలు సాపేక్షంగా సాపేక్షంగా కొనసాగాయి, రకాలు, తరగతులు, నేమ్‌స్పేస్‌ల పేర్లను భర్తీ చేసే మరియు మూలంలో చేర్చబడిన స్క్రిప్ట్‌ల సహాయంతో ఫైళ్లు. మైగ్రేషన్ 10 సోర్స్ ఫైల్‌లను ప్రభావితం చేసింది (000లో). wchar_t char14_tతో భర్తీ చేయబడింది; మేము wchar_t ఉపయోగాన్ని వదిలివేయాలని నిర్ణయించుకున్నాము, ఎందుకంటే char000_t అన్ని OSలలో 16 బైట్‌లను తీసుకుంటుంది మరియు Windows మరియు Linux మధ్య కోడ్ అనుకూలతను పాడు చేయదు.

చిన్న చిన్న సాహసాలు జరిగాయి. ఉదాహరణకు, STLPortలో ఒక ఎలిమెంట్‌కి పాయింటర్‌కి ఇటరేటర్ పరోక్షంగా ప్రసారం చేయబడుతుంది మరియు మా కోడ్‌లోని కొన్ని చోట్ల ఇది ఉపయోగించబడింది. కొత్త లైబ్రరీలలో దీన్ని చేయడం ఇకపై సాధ్యం కాదు మరియు ఈ భాగాలను విశ్లేషించి మానవీయంగా తిరిగి వ్రాయవలసి ఉంటుంది.

కాబట్టి, కోడ్ మైగ్రేషన్ పూర్తయింది, అన్ని ఆపరేటింగ్ సిస్టమ్‌లకు కోడ్ కంపైల్ చేయబడింది. ఇది పరీక్షల సమయం.

పరివర్తన తర్వాత పరీక్షలు కోడ్ యొక్క పాత వెర్షన్‌తో పోలిస్తే పనితీరులో తగ్గుదల (కొన్ని ప్రదేశాలలో 20-30% వరకు) మరియు మెమరీ వినియోగం (10-15% వరకు) పెరుగుదలను చూపించాయి. ఇది ముఖ్యంగా, ప్రామాణిక తీగల యొక్క ఉపశీర్షిక పనితీరు కారణంగా ఉంది. అందువల్ల, మేము మళ్ళీ మా స్వంత, కొద్దిగా సవరించిన పంక్తిని ఉపయోగించాల్సి వచ్చింది.

పొందుపరిచిన లైబ్రరీలలో కంటైనర్ల అమలు యొక్క ఆసక్తికరమైన లక్షణం కూడా వెల్లడైంది: ఖాళీ (మూలకాలు లేకుండా) std::map మరియు std::అంతర్నిర్మిత లైబ్రరీల నుండి సెట్ చేయబడినవి మెమరీని కేటాయిస్తాయి. మరియు అమలు లక్షణాల కారణంగా, కోడ్‌లోని కొన్ని ప్రదేశాలలో ఈ రకమైన ఖాళీ కంటైనర్లు చాలా సృష్టించబడతాయి. ప్రామాణిక మెమరీ కంటైనర్లు ఒక మూల మూలకం కోసం కొద్దిగా కేటాయించబడ్డాయి, కానీ మాకు ఇది క్లిష్టమైనదిగా మారింది - అనేక సందర్భాల్లో, మా పనితీరు గణనీయంగా పడిపోయింది మరియు మెమరీ వినియోగం పెరిగింది (STLPort తో పోలిస్తే). అందువల్ల, మా కోడ్‌లో మేము ఈ రెండు రకాల కంటైనర్‌లను అంతర్నిర్మిత లైబ్రరీల నుండి బూస్ట్ నుండి వాటి అమలుతో భర్తీ చేసాము, ఇక్కడ ఈ కంటైనర్‌లు ఈ ఫీచర్‌ను కలిగి లేవు మరియు ఇది మందగించడం మరియు పెరిగిన మెమరీ వినియోగంతో సమస్యను పరిష్కరించింది.

పెద్ద ప్రాజెక్ట్‌లలో పెద్ద ఎత్తున మార్పుల తర్వాత తరచుగా జరిగే విధంగా, సోర్స్ కోడ్ యొక్క మొదటి పునరావృతం సమస్యలు లేకుండా పని చేయలేదు మరియు ఇక్కడ, ముఖ్యంగా, Windows అమలులో డీబగ్గింగ్ ఇటరేటర్‌లకు మద్దతు ఉపయోగపడుతుంది. మేము దశలవారీగా ముందుకు సాగాము మరియు 2017 వసంతకాలం నాటికి (వెర్షన్ 8.3.11 1C:ఎంటర్‌ప్రైజ్) వలస పూర్తయింది.

ఫలితాలు

C++14 ప్రమాణానికి మారడానికి మాకు 6 నెలల సమయం పట్టింది. ఎక్కువ సమయం, ఒక (కానీ చాలా ఎక్కువ అర్హత కలిగిన) డెవలపర్ ప్రాజెక్ట్‌లో పనిచేశారు మరియు చివరి దశలో నిర్దిష్ట ప్రాంతాలకు బాధ్యత వహించే జట్ల ప్రతినిధులు - UI, సర్వర్ క్లస్టర్, అభివృద్ధి మరియు పరిపాలన సాధనాలు మొదలైన వాటిలో చేరారు.

స్టాండర్డ్ యొక్క తాజా వెర్షన్‌లకు మారడంపై మా పనిని మార్పు చాలా సులభతరం చేసింది. అందువలన, వెర్షన్ 1C:Enterprise 8.3.14 (అభివృద్ధిలో, వచ్చే ఏడాది ప్రారంభంలో విడుదల చేయడానికి షెడ్యూల్ చేయబడింది) ఇప్పటికే ప్రమాణానికి బదిలీ చేయబడింది C++17.

వలస తర్వాత, డెవలపర్‌లకు మరిన్ని ఎంపికలు ఉన్నాయి. ఇంతకుముందు మనకు మా స్వంత సవరించిన STL సంస్కరణ మరియు ఒక std నేమ్‌స్పేస్ ఉంటే, ఇప్పుడు మేము std నేమ్‌స్పేస్‌లో, stdx నేమ్‌స్పేస్‌లో అంతర్నిర్మిత కంపైలర్ లైబ్రరీల నుండి ప్రామాణిక తరగతులను కలిగి ఉన్నాము - మా పనుల కోసం ఆప్టిమైజ్ చేయబడిన మా లైన్‌లు మరియు కంటైనర్‌లు, బూస్ట్‌లో - బూస్ట్ యొక్క తాజా వెర్షన్. మరియు డెవలపర్ తన సమస్యలను పరిష్కరించడానికి ఉత్తమంగా సరిపోయే తరగతులను ఉపయోగిస్తాడు.

తరలింపు కన్స్ట్రక్టర్ల యొక్క "స్థానిక" అమలు కూడా అభివృద్ధిలో సహాయపడుతుంది (కన్స్ట్రక్టర్లను తరలించండి) అనేక తరగతులకు. ఒక తరగతికి మూవ్ కన్‌స్ట్రక్టర్ ఉంటే మరియు ఈ క్లాస్‌ను కంటైనర్‌లో ఉంచినట్లయితే, అప్పుడు STL కంటైనర్ లోపల మూలకాల కాపీని ఆప్టిమైజ్ చేస్తుంది (ఉదాహరణకు, కంటైనర్ విస్తరించినప్పుడు మరియు సామర్థ్యాన్ని మార్చడం మరియు మెమరీని మళ్లీ కేటాయించడం అవసరం).

ఒక చెంచా తారు

వలసల యొక్క అత్యంత అసహ్యకరమైన (కానీ క్లిష్టమైనది కాదు) పర్యవసానంగా మనం వాల్యూమ్‌లో పెరుగుదలను ఎదుర్కొంటున్నాము. obj ఫైళ్లు, మరియు అన్ని ఇంటర్మీడియట్ ఫైల్‌లతో బిల్డ్ యొక్క పూర్తి ఫలితం 60-70 GBని తీసుకోవడం ప్రారంభించింది. ఈ ప్రవర్తన ఆధునిక ప్రామాణిక లైబ్రరీల యొక్క ప్రత్యేకతల కారణంగా ఉంది, ఇవి ఉత్పత్తి చేయబడిన సేవా ఫైల్‌ల పరిమాణంలో తక్కువ క్లిష్టమైనవిగా మారాయి. ఇది కంపైల్ చేసిన అప్లికేషన్ యొక్క ఆపరేషన్‌ను ప్రభావితం చేయదు, కానీ ఇది అభివృద్ధిలో అనేక అసౌకర్యాలను కలిగిస్తుంది, ప్రత్యేకించి, ఇది సంకలన సమయాన్ని పెంచుతుంది. బిల్డ్ సర్వర్‌లు మరియు డెవలపర్ మెషీన్‌లలో ఖాళీ డిస్క్ స్థలం కోసం అవసరాలు కూడా పెరుగుతున్నాయి. మా డెవలపర్‌లు ప్లాట్‌ఫారమ్ యొక్క అనేక వెర్షన్‌లలో సమాంతరంగా పని చేస్తారు మరియు వందల కొద్దీ గిగాబైట్ల ఇంటర్మీడియట్ ఫైల్‌లు కొన్నిసార్లు వారి పనిలో ఇబ్బందులను సృష్టిస్తాయి. సమస్య అసహ్యకరమైనది, కానీ క్లిష్టమైనది కాదు; మేము దాని పరిష్కారాన్ని ప్రస్తుతానికి వాయిదా వేసాము. సాంకేతికతను పరిష్కరించే ఎంపికలలో ఒకటిగా మేము పరిగణిస్తున్నాము ఐక్యత నిర్మాణం (ముఖ్యంగా, Chrome బ్రౌజర్‌ను అభివృద్ధి చేస్తున్నప్పుడు Google దీన్ని ఉపయోగిస్తుంది).

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి