Hacker News

پہلا C++ (m) مختص ہمیشہ 72 KB کیوں ہوتا ہے؟

تبصرے

1 min read Via joelsiks.com

Mewayz Team

Editorial Team

Hacker News

آپ کی پہلی C++ مختص کے پیچھے کا راز

آپ ایک سادہ C++ پروگرام لکھتے ہیں۔ ایک نیا int۔ چار بائٹس۔ آپ اسٹریس یا اپنے پسندیدہ میموری پروفائلر کو فائر کرتے ہیں، اور یہ وہیں ہے — آپ کے عمل نے آپریٹنگ سسٹم سے تقریباً 72 KB کی درخواست کی ہے۔ 4 بائٹس نہیں۔ 64 بائٹس نہیں۔ ایک مکمل 72 KB۔ اگر آپ نے کبھی اس نمبر کو گھور کر سوچا ہے کہ کیا آپ کا ٹولنگ آپ سے جھوٹ بول رہا ہے، تو آپ اکیلے نہیں ہیں۔ یہ بظاہر عجیب و غریب رویہ C++ ڈویلپرز کے درمیان اکثر پوچھے جانے والے سوالات میں سے ایک ہے جو پہلی بار میموری انٹرنل میں کھود رہے ہیں، اور جواب ہمیں ان تہوں کے ذریعے ایک دلچسپ سفر پر لے جاتا ہے جو آپ کے کوڈ اور اصل ہارڈ ویئر کے درمیان بیٹھی ہیں۔

جب آپ نیا

کو کال کرتے ہیں تو کیا ہوتا ہے۔

72 KB کے اعداد و شمار کو سمجھنے کے لیے، آپ کو مکمل ایلوکیشن چین کو ٹریس کرنا ہوگا۔ جب آپ کا C++ کوڈ نئے int پر عمل درآمد کرتا ہے، تو کمپائلر اس کا ترجمہ آپریٹر نیو کو کال میں کرتا ہے، جو زیادہ تر لینکس سسٹمز پر glibc سے malloc کو ڈیلیٹ کرتا ہے۔ لیکن malloc براہ راست کرنل سے 4 بائٹس میموری کے لیے نہیں پوچھتا ہے۔ کرنل صفحات میں کام کرتا ہے - عام طور پر x86_64 پر 4 KB - اور سسٹم کال کی لاگت ایک سادہ میموری تک رسائی کے مقابلے میں بہت زیادہ ہے۔ ہر انفرادی مختص کے لیے brk() یا mmap() کو کال کرنے سے کوئی بھی غیر معمولی پروگرام رک جائے گا۔

اس کے بجائے، glibc کا میموری مختص کرنے والا — ایک نفاذ جسے ptmalloc2 کہا جاتا ہے، جو خود ڈوگ لی کے کلاسک dlmalloc سے نکلا ہے — ایک مڈل مین کے طور پر کام کرتا ہے۔ یہ دانا کے سامنے سے میموری کے بڑے بلاکس کی درخواست کرتا ہے، پھر انہیں چھوٹے ٹکڑوں میں تراشتا ہے جیسا کہ آپ کے پروگرام کو ان کی ضرورت ہے۔ یہ بنیادی وجہ ہے کہ آپ کی پہلی 4 بائٹ مختص آپریٹنگ سسٹم کے لیے بہت بڑی درخواست کو متحرک کرتی ہے۔ مختص کرنے والا فضول خرچ نہیں ہو رہا ہے۔ یہ اسٹریٹجک ہے۔

72 KB کو الگ کرنا: جہاں بائٹس جاتے ہیں

ابتدائی ایلوکیشن اوور ہیڈ کئی الگ الگ اجزاء سے آتا ہے جسے رن ٹائم کو شروع کرنا چاہیے اس سے پہلے کہ یہ آپ کو قابل استعمال میموری کا ایک بائٹ بھی دے سکے۔ ہر جزو کو سمجھنا اس بات کی وضاحت کرتا ہے کہ نمبر جہاں آتا ہے وہیں کیوں آتا ہے۔

سب سے پہلے، glibc کا malloc مین میدان کو شروع کرتا ہے - بنیادی بک کیپنگ ڈھانچہ جو مرکزی دھاگے پر تمام مختصات کو ٹریک کرتا ہے۔ اس میدان میں ہیپ کے لیے میٹا ڈیٹا، فری لسٹ پوائنٹرز، اور مختلف مختص سائز کے لیے بن ڈھانچے شامل ہیں۔ مختص کرنے والا پروگرام کے وقفے کو sbrk() کے ذریعے بڑھاتا ہے، اور ابتدائی توسیع M_TOP_PAD نامی ایک اندرونی پیرامیٹر کے ذریعے چلتی ہے، جو ڈیفالٹ 128 KB پیڈنگ پر ہے۔ تاہم، اصل ابتدائی درخواست کو صفحہ کی سیدھ اور موجودہ وقفے کی پوزیشن کے لیے ایڈجسٹ کیا جاتا ہے، جس کے نتیجے میں اکثر چھوٹی پہلی درخواست ہوتی ہے — عام طور پر نئے شروع ہونے والے عمل پر اس 72 KB کے اعداد و شمار کے قریب اترنا۔

دوسرا، glibc 2.26 کے بعد سے، مختص کرنے والا پہلے استعمال پر ایک تھریڈ-لوکل کیشے (tcache) کو شروع کرتا ہے۔ tcache میں 64 ڈبے ہوتے ہیں (ایک فی چھوٹے ایلوکیشن سائز کلاس)، ہر ایک 7 کیشڈ ٹکڑوں کو رکھنے کی صلاحیت رکھتا ہے۔ tcache_perthread_struct بذات خود 1 KB استعمال کرتا ہے، لیکن اسے شروع کرنے کا عمل وسیع میدان سیٹ اپ کو متحرک کرتا ہے۔ تیسرا، C++ رن ٹائم آپ کے main() کے چلنے سے پہلے ہی مختص کر چکا ہے — جامد کنسٹرکٹرز، std::cout اور دوستوں کے لیے iostream بفر انیشیلائزیشن، اور لوکیل سیٹ اپ سبھی اس ابتدائی ہیپ فوٹ پرنٹ میں حصہ ڈالتے ہیں۔

ارینا سسٹم اور کیوں پری ایلوکیشن سمارٹ ہے

میموری کا کافی حصہ پہلے سے مختص کرنے کا فیصلہ بجائے اس کے کہ اس کو ٹکڑے ٹکڑے کرنے کی درخواست کی جائے، عمل درآمد کا کوئی حادثہ نہیں ہے۔ یہ ایک دانستہ انجینئرنگ ٹریڈ آف ہے جس کی جڑیں کئی دہائیوں کے سسٹم پروگرامنگ کے تجربے میں ہیں۔ brk() یا mmap() پر ہر کال میں صارف کی جگہ سے کرنل اسپیس میں سیاق و سباق کا سوئچ، عمل کی ورچوئل میموری میپنگ میں ترمیم، اور ممکنہ صفحہ ٹیبل اپ ڈیٹ شامل ہوتا ہے۔ جدید ہارڈ ویئر پر، ایک سنگل سسٹم کال کی قیمت تقریباً 100-200 نینو سیکنڈز ہوتی ہے — تنہائی میں معمولی، پیمانے پر تباہ کن۔

ایک ایسے پروگرام پر غور کریں جو شروع کے دوران 10,000 چھوٹے مختص کرتا ہے۔ پہلے سے مختص کیے بغیر، اس کا مطلب ہوگا 10,000 سسٹم کالز، جس کی لاگت تقریباً 1-2 ملی سیکنڈ خالص اوور ہیڈ ہوگی۔ ارینا پر مبنی مختص کرنے والے کے ساتھ، پہلی ایلوکیشن سنگل سسٹم کال کو متحرک کرتی ہے، اور اس کے بعد 9,999 مختصات کو پوائنٹر ریاضی اور لنکڈ لسٹ آپریشنز کے ذریعے مکمل طور پر صارف کی جگہ پر پیش کیا جاتا ہے - ہر ایک تقریباً 10-50 نینو سیکنڈ لیتا ہے۔ ریاضی غیر مبہم ہے: پہلے سے مختص کرنا شدت کے حکم سے جیت جاتا ہے۔

آپ اپنی پہلی مختص پر جو 72 KB دیکھتے ہیں وہ ضائع شدہ میموری نہیں ہے - یہ کارکردگی کی سرمایہ کاری ہے۔ مختص کرنے والا شرط لگا رہا ہے کہ آپ کا پروگرام جلد ہی مزید مختص کرے گا، اور عملی طور پر ہر حقیقی دنیا کے منظر نامے میں، اس شرط کی ادائیگی اچھی طرح سے ہوتی ہے۔ جدید 64 بٹ سسٹمز پر غیر استعمال شدہ ورچوئل ایڈریس اسپیس کی قیمت بنیادی طور پر صفر ہے۔

ورچوئل میموری بمقابلہ جسمانی یادداشت: اس سے کوئی فرق کیوں نہیں پڑتا

پہلی بار اس رویے کا سامنا کرنے والے ڈویلپرز کے درمیان ایک عام تشویش وسائل کا ضیاع ہے۔ اگر مجھے صرف 4 بائٹس کی ضرورت ہے، تو میرا پروگرام 72 KB کیوں استعمال کر رہا ہے؟ اہم بصیرت یہ ہے کہ ورچوئل میموری جسمانی میموری نہیں ہے۔ جب glibc پروگرام کے وقفے کو 72 KB تک بڑھاتا ہے، تو کرنل اس عمل کی ورچوئل میموری میپنگ کو اپ ڈیٹ کرتا ہے، لیکن یہ فوری طور پر ان صفحات کو فزیکل RAM کے ساتھ بیک نہیں کرتا ہے۔ اصل فزیکل پیجز ڈیمانڈ پر صفحہ کی خرابیوں کے ذریعے مختص کیے جاتے ہیں — صرف اس وقت جب آپ کا پروگرام کسی مخصوص ایڈریس پر لکھتا ہے تو کرنل اسے میموری کا ایک حقیقی صفحہ تفویض کرتا ہے۔

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Start Free →

اس کا مطلب یہ ہے کہ اگرچہ آپ کے عمل کا ورچوئل سائز 72 KB تک بڑھ جاتا ہے، اس کا رہائشی سیٹ سائز (RSS) — اصل میں استعمال ہونے والی فزیکل RAM کی مقدار — صرف ان صفحات سے بڑھ جاتی ہے جنہیں آپ واقعی چھوتے ہیں۔ ایک نئے انٹ کے لیے، یہ عام طور پر ایک 4 KB صفحہ ہے، اس کے علاوہ جو بھی صفحات ایرینا میٹا ڈیٹا پر قبضہ کرتا ہے۔ بقیہ ورچوئل اسپیس وہیں بیٹھی ہے، استعمال کے لیے تیار ہے، اس کی قیمت ایڈریس اسپیس کے سوا کچھ نہیں ہے — جس میں سے آپ کے پاس 64 بٹ لینکس سسٹم پر 128 ٹی بی ہے۔

پروڈکشن ایپلی کیشنز کی پروفائلنگ اور نگرانی کرتے وقت یہ فرق اہم ہے۔ اگر آپ ایسا سافٹ ویئر بنا رہے ہیں جس کے لیے وسائل کی حقیقی کھپت کو ٹریک کرنے کی ضرورت ہے — چاہے وہ SaaS بیک اینڈ ہو، ایک مائیکرو سروس، یا ایک تجزیاتی پائپ لائن جیسا کہ پلیٹ فارمز پر چلتا ہے جیسا کہ Mewayz کاروباری کارروائیوں کے لیے — آپ کو ورچوئل سائز کے بجائے ہمیشہ RSS کی نگرانی کرنی چاہیے۔ /proc/[pid]/smaps، valgrind --tool=massif، اور pmap جیسے ٹولز آپ کو ورچوئل میموری کے اعداد و شمار کو گمراہ کرنے کے بجائے درست جسمانی میموری کے نشانات دے سکتے ہیں۔

مختلف مختص کرنے والے پہلے مختص کو کیسے ہینڈل کرتے ہیں

72 KB کا اعداد و شمار glibc کے ptmalloc2 کے لیے مخصوص ہے۔ دوسرے مختص کرنے والے مختلف تجارت کرتے ہیں، اور ابتدائی مختص اوور ہیڈ اسی کے مطابق مختلف ہوتا ہے۔ کارکردگی کے لحاظ سے حساس ایپلیکیشنز کے لیے مختص کرنے والے کا انتخاب کرتے وقت ان اختلافات کو سمجھنا قیمتی ہے۔

  • jemalloc (Facebook, FreeBSD کے ذریعے استعمال کیا جاتا ہے) — تھریڈ-لوکل کیشز کے ساتھ زیادہ دانے دار ایرینا ڈھانچہ استعمال کرتا ہے۔ ابتدائی اوور ہیڈ زیادہ ہوتا ہے (اکثر 200+ KB) لیکن کم لاک تنازعہ کی وجہ سے بہتر ملٹی تھریڈڈ کارکردگی پیش کرتا ہے۔
  • tcmalloc (Google's Thread-Caching Malloc) — جارحانہ پری ایلوکیشن کے ساتھ، ڈیفالٹ کے طور پر تقریباً 2 MB کا فی تھریڈ کیش مختص کرتا ہے۔ ابتدائی اوور ہیڈ زیادہ ہے، لیکن اس کے بعد کی چھوٹی مختصات انتہائی تیز ہیں۔
  • musl libc's malloc — تمام مختص کرنے کے لیے mmap پر مبنی ایک بہت آسان ڈیزائن استعمال کرتا ہے۔ ابتدائی اوور ہیڈ کم سے کم ہے (اکثر صرف 4 KB فی مختص)، لیکن زیادہ بار بار سسٹم کالز کی وجہ سے فی مختص لاگت زیادہ ہے۔
  • mimalloc (Microsoft) — 64 MB حصوں کے ساتھ سیگمنٹ پر مبنی مختص استعمال کرتا ہے۔ پہلی مختص ایک 64 MB ورچوئل ریزرویشن کو متحرک کرتی ہے (کم سے کم جسمانی عزم کے ساتھ)، غیر معمولی جگہ اور تھرو پٹ کے لیے تجارتی ایڈریس کی جگہ۔

ان مختص کرنے والوں کے درمیان انتخاب مکمل طور پر آپ کے کام کے بوجھ پر منحصر ہے۔ ہیوی ملٹی تھریڈڈ ایلوکیشن کے ساتھ طویل عرصے سے چلنے والی سرور ایپلی کیشنز کے لیے، jemalloc یا tcmalloc عام طور پر glibc کے ڈیفالٹ سے بہتر کارکردگی کا مظاہرہ کرتے ہیں۔ میموری سے محدود ایمبیڈڈ سسٹمز کے لیے، کم تھرو پٹ کے باوجود مسل کا آسان طریقہ بہتر ہوسکتا ہے۔ زیادہ تر عام مقصد کے ڈیسک ٹاپ اور سرور ایپلی کیشنز کے لیے، ptmalloc2 کا 72 KB ابتدائی اوور ہیڈ ایک معقول ڈیفالٹ کی نمائندگی کرتا ہے جو بغیر ٹیوننگ کے اچھی طرح کام کرتا ہے۔

ابتدائی ایلوکیشن رویے کو ٹیون کرنا

اگر پہلے سے طے شدہ 72 KB ابتدائی اوور ہیڈ آپ کے استعمال کے معاملے کے لیے حقیقی طور پر پریشانی کا باعث ہے — شاید آپ ہزاروں قلیل المدتی عمل کو جنم دے رہے ہیں، جن میں سے ہر ایک صرف مٹھی بھر مختص کرتا ہے — glibc mallopt() اور MALLOC_ خاندان کے متغیرات کے ذریعے کئی ٹیون ایبل فراہم کرتا ہے۔

M_TOP_PAD پیرامیٹر کنٹرول کرتا ہے کہ مختص کنندہ کتنی اضافی میموری کی درخواست کرتا ہے جس کی فوری ضرورت ہے۔ اسے mallopt(M_TOP_PAD, 0) کے ساتھ 0 پر سیٹ کرنا مختص کرنے والے سے کہتا ہے کہ صرف وہی درخواست کرے جس کی ضرورت ہے، ابتدائی اوور ہیڈ کو نمایاں طور پر کم کر کے۔ M_MMAP_THRESHOLD پیرامیٹر اس سائز کو کنٹرول کرتا ہے جس کے اوپر مختصات میدان کے بجائے mmap استعمال کرتے ہیں۔ M_TRIM_THRESHOLD کنٹرول کرتا ہے جب آزاد شدہ میموری OS پر واپس کی جاتی ہے۔ اور glibc 2.26 کے بعد سے، glibc.malloc.tcache_count اور glibc.malloc.tcache_max ٹیون ایبلز آپ کو تھریڈ کیشے کے رویے کو کنٹرول کرنے دیتے ہیں۔

تاہم، احتیاط کا ایک لفظ: محتاط بینچ مارکنگ کے بغیر ان پیرامیٹرز کو ٹیون کرنا تقریباً ہمیشہ ہی چیزوں کو مزید خراب کرتا ہے۔ ڈیفالٹس کا انتخاب وسیع حقیقی دنیا کی پروفائلنگ کی بنیاد پر کیا گیا تھا، اور وہ کام کے بوجھ کی اکثریت کے لیے ایک میٹھی جگہ کی نمائندگی کرتے ہیں۔ جب تک کہ آپ کے پاس پروڈکشن پروفائلنگ سے اس بات کا پختہ ثبوت نہیں ہے کہ malloc اوور ہیڈ ایک رکاوٹ ہے — اور آپ نے اپنی تبدیلیوں کے اثرات کو ناپا ہے — ڈیفالٹس کو ہی چھوڑ دیں۔ مختص کرنے والے کی قبل از وقت اصلاح یاک شیونگ کی ایک خاص طور پر کپٹی شکل ہے جس نے نہ ہونے کے برابر فائدے کے لیے انجینئرنگ کے لاتعداد گھنٹے استعمال کیے ہیں۔

یہ ہمیں سسٹمز پروگرامنگ کے بارے میں کیا سکھاتا ہے

72 KB کا پہلا مختص اسرار، اس کے بنیادی طور پر، تجریدی تہوں کے بارے میں ایک سبق ہے۔ C++ آپ کو یہ وہم فراہم کرتا ہے کہ نیا int 4 بائٹس مختص کرتا ہے۔ زبان کا معیار یہی کہتا ہے۔ آپ کا ذہنی ماڈل ایسا کہتا ہے۔ لیکن آپ کے کوڈ اور ہارڈ ویئر کے درمیان جدید ترین سسٹمز کا ایک ڈھیر بیٹھا ہوا ہے — C++ رن ٹائم، C لائبریری مختص کرنے والا، کرنل کا ورچوئل میموری سب سسٹم، اور ہارڈ ویئر کا MMU اور TLB — ہر ایک اپنے طرز عمل، اصلاح اور اوور ہیڈ کو شامل کرتا ہے۔

یہ کوئی خامی نہیں ہے۔ یہ سسٹم سافٹ ویئر کا پورا نقطہ ہے۔ ہر پرت ایک حقیقی مسئلہ کو حل کرنے کے لیے موجود ہے: مختص کرنے والا موجود ہے لہذا آپ کو ہر مختص کے لیے سسٹم کال کرنے کی ضرورت نہیں ہے۔ ورچوئل میموری سسٹم موجود ہے لہذا آپ کو جسمانی میموری کو براہ راست منظم کرنے کی ضرورت نہیں ہے۔ صفحہ فالٹ ہینڈلر موجود ہے لہذا میموری سستی اور مؤثر طریقے سے انجام دی جاتی ہے۔ ہر پرت بڑی مقدار میں کارکردگی اور سہولت کے لیے تھوڑی مقدار میں شفافیت کا سودا کرتی ہے۔

ڈیولپرز جو سب سے زیادہ قابل اعتماد، اعلیٰ کارکردگی کا مظاہرہ کرنے والے نظام بناتے ہیں وہ ہیں جو ان تہوں کو سمجھتے ہیں — اس لیے نہیں کہ انہیں ان کے بارے میں مسلسل سوچنے کی ضرورت ہے، بلکہ اس لیے کہ جب کچھ غیر متوقع ہوتا ہے (جیسے کہ ایک پراسرار 72 KB مختص)، ان کے پاس یہ سمجھنے کا ذہنی نمونہ ہوتا ہے کہ کیوں۔ چاہے آپ ریئل ٹائم ٹریڈنگ سسٹم، گیم انجن، یا ہزاروں صارفین کی خدمت کرنے والا بزنس پلیٹ فارم بنا رہے ہوں، اس بارے میں استدلال کرنے کی صلاحیت کہ سسٹم کی سطح پر آپ کا کوڈ اصل میں کیا کرتا ہے وہی ہے جو قابل ڈویلپرز کو غیر معمولی لوگوں سے الگ کرتا ہے۔ 72 KB کوئی بگ نہیں ہے۔ یہ آپ کا مختص کرنے والا اپنا کام شاندار طریقے سے کر رہا ہے۔

آج ہی اپنا بزنس OS بنائیں

فری لانسرز سے لے کر ایجنسیوں تک، Mewayz 207 مربوط ماڈیولز کے ساتھ 138,000+ کاروباروں کو طاقت دیتا ہے۔ مفت شروع کریں، جب آپ بڑھیں تو اپ گریڈ کریں۔

مفت اکاؤنٹ بنائیں →

Start managing your business smarter today

Join 30,000+ businesses. Free forever plan · No credit card required.

Ready to put this into practice?

Join 30,000+ businesses using Mewayz. Free forever plan — no credit card required.

Start Free Trial →

Ready to take action?

Start your free Mewayz trial today

All-in-one business platform. No credit card required.

Start Free →

14-day free trial · No credit card · Cancel anytime