در مقالهی «نکات و ترفندهای بهینهسازی برنامه C برای میکروکنترلر AVR-قسمت اول» به معماری میکروکنترلرهای ۸بیتی AVR و کامپایلر GCC و نکات بهینه سازی حجم برنامه C پرداختیم. در مقاله پیش رو با نکات بیشتری مربوط به کاهش حجم کد برنامه برای بهینه سازی برنامه C آشنا میشویم.
نکات و ترفندهای کاهش حجم برنامه برای بهینه سازی برنامه C
5)ثوابت در برنامه
متغیرها و جداول و آرایههایی که ثابت هستند و مقدار آنها در طول برنامه تغییر نمیکنند معمولا در حافظهی فقط خواندنی Flash یا EEPROM ذخیره میشوند تا حافظهی باارزش SRAM اشغال نشود. همانطور که میدانیم ثوابت بهصورت عمومی استفاده میشوند و در توابع قابل اعلان نیستند. با نوشتن کلمهی کلیدی «const» در برنامهی C، میتوان برای کامپایلر مشخصکرد که این مقدار درطول برنامه تغییر نخواهدکرد و یک دادهی فقط خواندنی (Read-Only) است. با اینکار فرصتهای بهینهسازی برنامه C توسط کامپایلر افزایش مییابد. با اینحال با این کلمهی کلیدی، نوع حافظهی ذخیرهکنندهی داده تعیین نمیشود. در کامپایلر GCC، برای ذخیرهی داده در حافظهی فقط خواندنی برنامه میتوان از ماکروی «PROGMEM» و تابع «pgm_read_byte» استفاده کرد. این ماکرو و تابع در فایل هدر avr/pgmspace.h تعریف شدهاند. در مثالزیر میتوان تاثیر این تابع را در کاهش حجم اشغالی SRAM مشاهده کرد. حجم اشغالشده در هردو حافظهی برنامه و داده کاهش یافته و منجربه بهینهسازی حجم برنامه C شدهاست.
باید توجهداشت بهخاطراینکه سرعت خواندن داده از حافظهی برنامه نسبت به حافظهی داده کندتر است، overhead به وجود میآید، بنابراین اگر نیاز است در برنامه چندبار این مقدار ثابت خواندهشود بهجای بهکاربردن ماکروی PROGMEM بهتر است از متغیرهای موقت (temporary variable) استفاده کنیم. گفتنیاست در کامپایلر کدویژن، نوشتن کلمهی کلیدی «flash» در ابتدای تعریف ثوابت برای کامپایلر مشخص میکند که مکان ذخیرهی داده در حافظهی برنامه است. اگر از کلمهی کلیدی «flash» استفاده نشود ثابت در حافظهی فلش ذخیره میشود ولی حافظهی SRAM نیز اشغال خواهد شد چرا که مقدار ثابت از حافظهی فلش در SRAM کپی میشود و در هنگام اجرا مقدار از حافظهی SRAM خوانده میشود.
6) انواع دسترسی استاتیک (Static)
برای دادههای عمومی (global) تا جاییکه امکاندارد از کلمهی کلیدی «static» استفادهکنید. اگر متغیرهای عمومی با کلمهی کلیدی«static» تعریف شوند، تنها در فایلی که تعریف شدهاند قابل دسترسی هستند. با این روش از استفادهی متغیر عمومی در دیگر فایلها به عنوان متغیر خارجی (external variable) جلوگیری میشود. ازسویدیگر تا جاییکه امکان دارد کلمهی کلیدی «static» را برای متغیرهای محلی (local) داخل توابع استفاده نکنید. مقدار یک متغیر محلی استاتیک پساز اتمام اجرای تابع تا فراخوانی بعدی تابع باید حفظ شود. بنابراین حافظهی SRAM بهصورت پیوسته در طول اجرای برنامه اشغال خواهد شد. میتوان گفت متغیر محلی استاتیک مانند یک متغیر عمومی خواهد بود بااین تفاوتکه فقط برای یک تابع خاص در دسترس است. توابع استاتیک برای بهینهسازی برنامه برتری دارند چون تنها در همان فایل قابل دسترس هستند و توسط دیگر فایلها قابل فراخوانی نیستند. اگر تابع استاتیک تنها یکبار در فایل فراخوانی شود و تنظیمات بهینهسازی ( O3 , -O2 , -O1 , -Os- ) فعال باشد، تابع استاتیک به صورت یک تابع inline درنظر گرفتهمیشود و کد اسمبلی برای آن تولید نخواهد شد. اگر تابع استاتیک بیشاز یکبار در برنامه فراخوانی شود در کامپایلر به عنوان تابع inline در نظر گرفته نمیشود.
7)دستورات سطح پایین زبان اسمبلی
برنامه با دستورات کد شده با زبان اسمبلی، بهینهترین کد به شمار میآید. یکیاز عیبهای کد اسمبلی غیرقابل حمل بودن (non-portable) است بنابراین به برنامهنویسان توصیه نمیشود. بااینحال استفادهاز ماکروهای اسمبلی، خوانایی و قابل حمل بودن را بهبود میدهد. از ماکروهای اسمبلی بهجای توابع استفاده کنید. برای آشنایی با ماکروهای اسمبلی به بخش راهنمای « Inline Assembler Cookbook » رجوع کنید.
نکات مربوط به بهینهسازی حجم برنامه C بهطور کامل بیانشد. در قسمت بعدی مقاله به بهینهسازی سرعت اجرای برنامه و کاهش زمان اجرا میپردازیم.
منبع: سیسوگ