کس طرح ہم نے C++ کوڈ کی 10 ملین لائنوں کا ترجمہ C++14 معیار (اور پھر C++17 میں) کیا

کچھ عرصہ پہلے (2016 کے موسم خزاں میں)، 1C:Enterprise ٹیکنالوجی پلیٹ فارم کے اگلے ورژن کی ترقی کے دوران، نئے معیار کی حمایت کرنے کے بارے میں ترقیاتی ٹیم کے اندر سوال پیدا ہوا تھا۔ سی ++ 14 ہمارے کوڈ میں۔ ایک نئے معیار پر منتقلی، جیسا کہ ہم نے فرض کیا، ہمیں بہت سی چیزوں کو زیادہ خوبصورت، سادہ اور قابل اعتماد طریقے سے لکھنے کی اجازت دے گا، اور کوڈ کی مدد اور دیکھ بھال کو آسان بنائے گا۔ اور ایسا لگتا ہے کہ ترجمے میں کوئی غیر معمولی چیز نہیں ہے، اگر کوڈ بیس کے پیمانے اور ہمارے کوڈ کی مخصوص خصوصیات کے لیے نہیں۔

ان لوگوں کے لیے جو نہیں جانتے ہیں، 1C:Enterprise کراس پلیٹ فارم کاروباری ایپلی کیشنز کی تیز رفتار ترقی اور مختلف OS اور DBMSs پر ان کے نفاذ کے لیے رن ٹائم کا ماحول ہے۔ عام شرائط میں، مصنوعات پر مشتمل ہے:

  • ایپلیکیشن سرور کلسٹر، ونڈوز اور لینکس پر چلتا ہے۔
  • گاہک, HTTP(s) یا اس کے اپنے بائنری پروٹوکول کے ذریعے سرور کے ساتھ کام کرنا، Windows, Linux, macOS پر کام کرتا ہے
  • ویب کلائنٹ، کروم، انٹرنیٹ ایکسپلورر، مائیکروسافٹ ایج، فائر فاکس، سفاری براؤزرز میں چل رہا ہے (جاوا اسکرپٹ میں لکھا ہوا)
  • ترقیاتی ماحول (کنفیگریٹر)، ونڈوز، لینکس، میک او ایس پر کام کرتا ہے۔
  • ایڈمنسٹریشن ٹولز ایپلیکیشن سرورز، ونڈوز، لینکس، میک او ایس پر چلتے ہیں۔
  • موبائل کلائنٹ, HTTP(s) کے ذریعے سرور سے منسلک ہونا، Android، iOS، Windows چلانے والے موبائل آلات پر کام کرتا ہے۔
  • موبائل پلیٹ فارم - اینڈرائیڈ، آئی او ایس، ونڈوز پر چلتے ہوئے مطابقت پذیری کی صلاحیت کے ساتھ آف لائن موبائل ایپلیکیشنز بنانے کا فریم ورک
  • ترقی کا ماحول 1C: انٹرپرائز ڈویلپمنٹ ٹولز، جاوا میں لکھا گیا۔
  • سرور تعامل کے نظام

ہم ہر ممکن حد تک مختلف آپریٹنگ سسٹمز کے لیے ایک ہی کوڈ لکھنے کی کوشش کرتے ہیں - سرور کوڈ بیس 99% عام ہے، کلائنٹ کوڈ بیس تقریباً 95% ہے۔ 1C: انٹرپرائز ٹیکنالوجی پلیٹ فارم بنیادی طور پر C++ میں لکھا گیا ہے اور کوڈ کی تخمینی خصوصیات ذیل میں دی گئی ہیں:

  • C++ کوڈ کی 10 ملین لائنیں،
  • 14 ہزار فائلیں،
  • 60 ہزار کلاسز،
  • نصف ملین طریقے.

اور ان تمام چیزوں کو C++14 میں ترجمہ کرنا تھا۔ آج ہم آپ کو بتائیں گے کہ ہم نے یہ کیسے کیا اور اس عمل میں ہمیں کیا سامنا کرنا پڑا۔

کس طرح ہم نے C++ کوڈ کی 10 ملین لائنوں کا ترجمہ C++14 معیار (اور پھر C++17 میں) کیا

دستبرداری

سست/تیز کام کے بارے میں ذیل میں لکھی گئی ہر چیز، (نہیں) مختلف لائبریریوں میں معیاری کلاسوں کے نفاذ کے ذریعے بڑی میموری کی کھپت کا ایک مطلب ہے: یہ ہمارے لیے درست ہے۔ یہ بہت ممکن ہے کہ معیاری نفاذ آپ کے کاموں کے لیے بہترین ہو گا۔ ہم نے اپنے کاموں سے آغاز کیا: ہم نے ڈیٹا لیا جو ہمارے کلائنٹس کے لیے عام تھا، ان پر مخصوص منظرنامے چلائے، کارکردگی کو دیکھا، میموری کی مقدار وغیرہ کو دیکھا، اور تجزیہ کیا کہ آیا ہم اور ہمارے کلائنٹس ایسے نتائج سے مطمئن ہیں یا نہیں۔ . اور انہوں نے اس پر منحصر عمل کیا۔

جو ہمارے پاس تھا۔

ابتدائی طور پر، ہم نے Microsoft Visual Studio میں 1C:Enterprise 8 پلیٹ فارم کے لیے کوڈ لکھا۔ یہ پروجیکٹ 2000 کی دہائی کے اوائل میں شروع ہوا تھا اور ہمارے پاس صرف ونڈوز ورژن تھا۔ قدرتی طور پر، اس کے بعد سے کوڈ کو فعال طور پر تیار کیا گیا ہے، بہت سے میکانزم کو مکمل طور پر دوبارہ لکھا گیا ہے. لیکن کوڈ 1998 کے معیار کے مطابق لکھا گیا تھا، اور، مثال کے طور پر، ہمارے دائیں زاویہ کے بریکٹ کو خالی جگہوں سے الگ کیا گیا تھا تاکہ تالیف کامیاب ہو، اس طرح:

vector<vector<int> > IntV;

2006 میں، پلیٹ فارم ورژن 8.1 کی ریلیز کے ساتھ، ہم نے لینکس کو سپورٹ کرنا شروع کیا اور تیسری پارٹی کی معیاری لائبریری میں تبدیل ہو گئے۔ ایس ٹی ایل پورٹ. منتقلی کی ایک وجہ وسیع لائنوں کے ساتھ کام کرنا تھا۔ ہمارے کوڈ میں، ہم std::wstring استعمال کرتے ہیں، جو کہ wchar_t قسم پر مبنی ہے۔ ونڈوز میں اس کا سائز 2 بائٹس ہے، اور لینکس میں ڈیفالٹ 4 بائٹس ہے۔ یہ کلائنٹ اور سرور کے ساتھ ساتھ مختلف مستقل ڈیٹا کے درمیان ہمارے بائنری پروٹوکول کی عدم مطابقت کا باعث بنا۔ جی سی سی کے اختیارات کا استعمال کرتے ہوئے، آپ یہ بتا سکتے ہیں کہ تالیف کے دوران wchar_t کا سائز بھی 2 بائٹس ہے، لیکن پھر آپ کمپائلر سے معیاری لائبریری استعمال کرنا بھول سکتے ہیں، کیونکہ یہ glibc استعمال کرتا ہے، جو بدلے میں 4 بائٹ wchar_t کے لیے مرتب کیا جاتا ہے۔ دیگر وجوہات میں معیاری کلاسوں کا بہتر نفاذ، ہیش ٹیبلز کے لیے سپورٹ، اور کنٹینرز کے اندر منتقل ہونے کے سیمنٹکس کی ایمولیشن بھی تھی، جسے ہم نے فعال طور پر استعمال کیا۔ اور ایک اور وجہ، جیسا کہ وہ کہتے ہیں آخری لیکن کم از کم، سٹرنگ کی کارکردگی تھی۔ ڈور کے لیے ہماری اپنی کلاس تھی، کیونکہ... ہمارے سافٹ ویئر کی تفصیلات کی وجہ سے، سٹرنگ آپریشنز بہت وسیع پیمانے پر استعمال کیے جاتے ہیں اور ہمارے لیے یہ بہت اہم ہے۔

ہماری سٹرنگ 2000 کی دہائی کے اوائل میں بیان کردہ سٹرنگ آپٹیمائزیشن کے خیالات پر مبنی ہے۔ آندرے الیگزینڈرسکو. بعد میں، جب الیگزینڈرسکو نے فیس بک پر کام کیا، تو ان کی تجویز پر، فیس بک کے انجن میں ایک لائن استعمال کی گئی جو اسی طرح کے اصولوں پر کام کرتی تھی (لائبریری دیکھیں حماقت).

ہماری لائن نے دو اہم اصلاحی ٹیکنالوجیز کا استعمال کیا:

  1. مختصر اقدار کے لیے، سٹرنگ آبجیکٹ میں ہی ایک اندرونی بفر استعمال کیا جاتا ہے (اضافی میموری مختص کرنے کی ضرورت نہیں ہے)۔
  2. باقی سب کے لیے میکانکس استعمال کیے جاتے ہیں۔ لکھنے پر کاپی کریں۔. سٹرنگ ویلیو کو ایک جگہ پر محفوظ کیا جاتا ہے، اور تفویض/ترمیم کے دوران ایک حوالہ کاؤنٹر استعمال کیا جاتا ہے۔

پلیٹ فارم کی تالیف کو تیز کرنے کے لیے، ہم نے اپنے STLPport ویرینٹ (جسے ہم نے استعمال نہیں کیا) سے اسٹریم کے نفاذ کو خارج کر دیا، اس سے ہمیں تقریباً 20% تیز تالیف ملی۔ اس کے بعد ہمیں محدود استعمال کرنا پڑا فروغ دینے کے. بوسٹ اسٹریم کا بہت زیادہ استعمال کرتا ہے، خاص طور پر اس کی سروس APIs میں (مثال کے طور پر، لاگنگ کے لیے)، اس لیے ہمیں اسٹریم کے استعمال کو ہٹانے کے لیے اس میں ترمیم کرنا پڑی۔ اس کے نتیجے میں، ہمارے لیے بوسٹ کے نئے ورژنز پر منتقل ہونا مشکل ہو گیا۔

تیسرا راستہ

C++ 14 معیار پر جانے پر، ہم نے درج ذیل اختیارات پر غور کیا:

  1. STLPport کو اپ گریڈ کریں جسے ہم نے C++14 معیار میں تبدیل کیا ہے۔ آپشن بہت مشکل ہے، کیونکہ... STLPport کے لیے سپورٹ 2010 میں بند کر دی گئی تھی، اور ہمیں اس کے تمام کوڈ خود بنانا ہوں گے۔
  2. C++14 کے ساتھ مطابقت رکھنے والے دوسرے STL نفاذ میں منتقلی۔ یہ انتہائی ضروری ہے کہ یہ عمل ونڈوز اور لینکس کے لیے ہو۔
  3. ہر OS کے لیے مرتب کرتے وقت، متعلقہ کمپائلر میں بنی لائبریری کا استعمال کریں۔

پہلے آپشن کو بہت زیادہ کام کی وجہ سے یکسر مسترد کر دیا گیا۔

ہم نے کچھ دیر دوسرے آپشن کے بارے میں سوچا۔ امیدوار کے طور پر سمجھا جاتا ہے۔ libc++، لیکن اس وقت یہ ونڈوز کے تحت کام نہیں کرتا تھا۔ libc++ کو ونڈوز میں پورٹ کرنے کے لیے، آپ کو بہت زیادہ کام کرنا پڑے گا - مثال کے طور پر، وہ سب کچھ خود لکھیں جس کا تعلق تھریڈز، تھریڈ سنکرونائزیشن اور ایٹمیسیٹی سے ہے، کیونکہ ان علاقوں میں libc++ استعمال ہوتا ہے۔ POSIX API.

اور ہم نے تیسرا راستہ اختیار کیا۔

منتقلی

لہذا، ہمیں متعلقہ کمپائلرز کی لائبریریوں کے ساتھ STLPport کے استعمال کو تبدیل کرنا پڑا (ونڈوز کے لیے Visual Studio 2015، Linux کے لیے gcc 7، macOS کے لیے clang 8)۔

خوش قسمتی سے، ہمارا کوڈ بنیادی طور پر رہنما خطوط کے مطابق لکھا گیا تھا اور اس میں ہر طرح کی ہوشیار چالوں کا استعمال نہیں کیا گیا تھا، اس لیے نئی لائبریریوں کی منتقلی نسبتاً آسانی سے آگے بڑھی، اسکرپٹ کی مدد سے جس نے قسموں، کلاسوں، نام کی جگہوں اور ماخذ کے ناموں کو تبدیل کر دیا۔ فائلوں. منتقلی نے 10 سورس فائلوں کو متاثر کیا (000 میں سے)۔ wchar_t کو char14_t سے بدل دیا گیا تھا۔ ہم نے wchar_t کا استعمال ترک کرنے کا فیصلہ کیا، کیونکہ char000_t تمام OS پر 16 بائٹس لیتا ہے اور ونڈوز اور لینکس کے درمیان کوڈ کی مطابقت کو خراب نہیں کرتا ہے۔

کچھ چھوٹے ایڈونچر تھے۔ مثال کے طور پر، STLPport میں ایک ایٹریٹر کو کسی عنصر کے پوائنٹر پر واضح طور پر کاسٹ کیا جا سکتا ہے، اور ہمارے کوڈ میں کچھ جگہوں پر یہ استعمال کیا گیا تھا۔ نئی لائبریریوں میں اب ایسا کرنا ممکن نہیں تھا، اور ان اقتباسات کا تجزیہ کرکے انہیں دستی طور پر دوبارہ لکھنا پڑتا تھا۔

لہذا، کوڈ کی منتقلی مکمل ہو گئی ہے، کوڈ تمام آپریٹنگ سسٹمز کے لیے مرتب کیا گیا ہے۔ یہ ٹیسٹوں کا وقت ہے۔

منتقلی کے بعد ہونے والے ٹیسٹوں نے کوڈ کے پرانے ورژن کے مقابلے کارکردگی میں کمی (کچھ جگہوں پر 20-30% تک) اور میموری کی کھپت میں (10-15% تک) اضافہ دکھایا۔ یہ خاص طور پر معیاری تاروں کی سب سے زیادہ کارکردگی کی وجہ سے تھا۔ لہذا، ہمیں دوبارہ اپنی، قدرے ترمیم شدہ لائن کا استعمال کرنا پڑا۔

ایمبیڈڈ لائبریریوں میں کنٹینرز کے نفاذ کی ایک دلچسپ خصوصیت بھی سامنے آئی: خالی (عناصر کے بغیر) std::map اور std:: بلٹ ان لائبریریوں سے سیٹ میموری کو مختص کرتے ہیں۔ اور نفاذ کی خصوصیات کی وجہ سے، کوڈ میں کچھ جگہوں پر اس قسم کے بہت سے خالی کنٹینرز بنائے گئے ہیں۔ معیاری میموری کنٹینرز کو تھوڑا سا مختص کیا جاتا ہے، ایک بنیادی عنصر کے لیے، لیکن ہمارے لیے یہ اہم ثابت ہوا - بہت سے منظرناموں میں، ہماری کارکردگی میں نمایاں کمی آئی اور میموری کی کھپت میں اضافہ ہوا (STLPport کے مقابلے)۔ لہذا، اپنے کوڈ میں ہم نے ان دونوں قسم کے کنٹینرز کو بلٹ ان لائبریریوں سے ان کے بوسٹ کے نفاذ کے ساتھ تبدیل کر دیا، جہاں ان کنٹینرز میں یہ خصوصیت نہیں تھی، اور اس نے سست روی اور میموری کی کھپت میں اضافہ کا مسئلہ حل کر دیا۔

جیسا کہ اکثر بڑے پروجیکٹس میں بڑے پیمانے پر تبدیلیوں کے بعد ہوتا ہے، سورس کوڈ کا پہلا تکرار بغیر کسی پریشانی کے کام نہیں کرتا تھا، اور یہاں، خاص طور پر، ونڈوز کے نفاذ میں ڈیبگنگ ایٹیریٹرز کے لیے سپورٹ کام آیا۔ قدم بہ قدم ہم آگے بڑھے، اور 2017 کے موسم بہار تک (ورژن 8.3.11 1C:Enterprise) منتقلی مکمل ہو گئی۔

کے نتائج

C++ 14 معیار میں منتقلی میں ہمیں تقریباً 6 مہینے لگے۔ زیادہ تر وقت، ایک (لیکن انتہائی قابل) ڈویلپر نے پروجیکٹ پر کام کیا، اور آخری مرحلے میں مخصوص علاقوں کے لیے ذمہ دار ٹیموں کے نمائندے شامل ہوئے - UI، سرور کلسٹر، ترقی اور انتظامیہ کے اوزار، وغیرہ۔

منتقلی نے معیار کے تازہ ترین ورژنز پر منتقلی کے ہمارے کام کو بہت آسان بنا دیا۔ اس طرح، ورژن 1C: انٹرپرائز 8.3.14 (ترقی میں، اگلے سال کے اوائل میں ریلیز ہونا) پہلے ہی معیار پر منتقل ہو چکا ہے۔ C++17.

منتقلی کے بعد، ڈویلپرز کے پاس مزید اختیارات ہوتے ہیں۔ اگر پہلے ہمارے پاس ایس ٹی ایل کا اپنا ترمیم شدہ ورژن اور ایک ایس ٹی ڈی نیم اسپیس تھا، تو اب ہمارے پاس ایس ٹی ڈی نیم اسپیس، ایس ٹی ڈی ایکس نیم اسپیس میں بلٹ ان کمپائلر لائبریریوں سے معیاری کلاسز ہیں - ہماری لائنیں اور کنٹینرز ہمارے کاموں کے لیے موزوں ہیں، فروغ میں - فروغ کا تازہ ترین ورژن۔ اور ڈویلپر ان کلاسوں کا استعمال کرتا ہے جو اس کے مسائل کو حل کرنے کے لیے موزوں ترین ہیں۔

موو کنسٹرکٹرز کا "مقامی" نفاذ بھی ترقی میں مدد کرتا ہے (تعمیر کنندگان کو منتقل کریں۔) کئی کلاسوں کے لیے۔ اگر کسی کلاس میں موو کنسٹرکٹر ہوتا ہے اور اس کلاس کو کنٹینر میں رکھا جاتا ہے، تو STL کنٹینر کے اندر موجود عناصر کی کاپی کو بہتر بناتا ہے (مثال کے طور پر، جب کنٹینر کو بڑھایا جاتا ہے اور اس کی صلاحیت کو تبدیل کرنا اور میموری کو دوبارہ مختص کرنا ضروری ہوتا ہے)۔

مرہم میں اڑنا

شاید ہجرت کا سب سے ناخوشگوار (لیکن اہم نہیں) نتیجہ یہ ہے کہ ہمیں حجم میں اضافے کا سامنا کرنا پڑتا ہے۔ obj فائلیں، اور تمام انٹرمیڈیٹ فائلوں کے ساتھ تعمیر کا مکمل نتیجہ 60-70 GB تک لے جانے لگا۔ یہ طرز عمل جدید معیاری لائبریریوں کی خصوصیات کی وجہ سے ہے، جو کہ جنریٹڈ سروس فائلوں کے سائز کے لحاظ سے کم اہم ہو گئی ہیں۔ یہ مرتب کردہ ایپلیکیشن کے عمل کو متاثر نہیں کرتا ہے، لیکن یہ ترقی میں بہت سی تکلیفوں کا سبب بنتا ہے، خاص طور پر، اس سے تالیف کا وقت بڑھ جاتا ہے۔ بلڈ سرورز اور ڈویلپر مشینوں پر مفت ڈسک کی جگہ کی ضروریات بھی بڑھ رہی ہیں۔ ہمارے ڈویلپر پلیٹ فارم کے متعدد ورژنز پر متوازی طور پر کام کرتے ہیں، اور سینکڑوں گیگا بائٹس کی انٹرمیڈیٹ فائلیں بعض اوقات ان کے کام میں مشکلات پیدا کرتی ہیں۔ مسئلہ ناخوشگوار ہے، لیکن نازک نہیں؛ ہم نے اس کا حل ابھی کے لیے ملتوی کر دیا ہے۔ ہم ٹیکنالوجی کو حل کرنے کے لیے ایک آپشن کے طور پر غور کر رہے ہیں۔ اتحاد کی تعمیر (خاص طور پر، گوگل اسے کروم براؤزر تیار کرتے وقت استعمال کرتا ہے)۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں