اینم یه تجربه پراکنده دیگه!
نوشتن این روزها سخت شده ولی من باز سعی میکنم که یه حضور کمرنگی در صحنه داشته باشم. این دفعه میخواستم در مورد یه موضوع جالب مرتبط با متغیر در سی بنویسیم
ما یه کد سی داشتیم که یه متغیر [local] با حجم حدودا ۱۰ کیلو بایت تعریف شده بود و مقدار دهی اولیه شده بود(عکس بود). همیشه کامپایلر به این قسمت از کد که میرسید کلی طول میکشید تا بتونه کد رو کامپایل کنه و همیشه اعصاب ما رو خورد میکرد. تا اینکه یه روز تصمیم گرفتیم مشکل رو حل کنیم. راه حلهایی که پیش رومون بود اینها:
- متغیر رو کلا حذف کنیم. که خب نمیخواستیم صورت مساله رو حذف کنیم
- متغیر رو [global] میکردیم که خب همه میتونستن تغییرش بدن و برامون بد بود
- متغیر رو [static] کنیم. این تفاوتی برای ما نداشت فقط میخواستیم امتحان کنیم.
خب اول راه دوم رو امتحان کردیم. اتفاقا هم زمان کامپایل کم شد و هم حجم باینری تولید شده. وقتی راه سوم رو هم امتحان کردیم دیدیم که نتیجه با راه دوم یکیه و حجم باینری کم شده و این خوب بود. چون راه دوم ویژگیهای متغیر [local] رو داشت و عیب در دسترس بودن برای همه رو هم نداشت.
سوالی که برای ما پیش اومد این بود که چرا یه تغییر اینجوری اینهمه هم توی سرعت هم حجم باینری موثره؟ برای جواب دادن به این ماجرا یکم رفتم تحقیق کردم:
- همه باینریها از بخشهای مختلفی تشکلی شدن که اگه [assembly] یادتون باشه شامل اینهاست
- بخش کد یا [code segment]
- بخش پشته یا [stack segment]
- بخش داده یا [data segment]
- متوجه شدم که متغیرهای [global] توی [data segment] تعریف میشن و متغیرهای [local] توی [stack segment] تعریف میشن.
- متوجه شدم که متغیرهای static هم توی [data segment] تعریف میشن.
پس هرچی بود زیر سر [data segment] بود از اینجا به بعدش بازی شد حدس و گمان در مورد چرایی دوتا اتفاق:
- چرا سرعت کامپیال بیشتر؟ احتمالا به این دلیل که کامپایلر با [data segment] راحتتر کار میکنه تا [stack segment]. اما این حدس حجم باینری کمتر رو توجیه نمیکنه چون در این دوحالت حجم متغیر ثابت مونده
- چرا حجم باینری کمتر؟ برای اینکار یکم باید یادمون بیاد توی [assembly] که چطور یه متغیر [local] تعریف میشه منظورم هست. یه متغیر [local] عملا اینه که اول یه مقداری توی stack قرار میگیره و در یه مرحله دیگه اون مقدار از stack خارج میشه. که این هم نیاز به کد سمت [code segment] داره هم نیاز به حافظه سمت [stack segment] داره.
خب با این حالت ما به حدس دقیق تری از اتفاق پشت پرده رسیدیم. اونم اینه که وقتی متغیر توی [data segment] قرار میگیره یه بخش توسط کامپایلر تخصیص داده میشه و مقادیر هم توی اون خونهها نوشته میشه. ولی وقتی قرار باشه اون متغیر توی [stack segment] قرار بگیره هم کد تولید میشه هم حافظه تخصیص داده میشه که منجر به طولانی تر شدن کل روند میشه.
امیدوارم به دردتون خورده باشه همین! [local]:https://en.wikipedia.org/wiki/Local_variable [global]:https://en.wikipedia.org/wiki/Global_variable [static]:https://en.wikipedia.org/wiki/Static_variable [data segment]:https://en.wikipedia.org/wiki/Data_segment [code segment]:https://en.wikipedia.org/wiki/Code_segment [stack segment]:https://en.wikipedia.org/wiki/Data_segment#Stack [assembly]:https://en.wikipedia.org/wiki/Assembly_language