لوآ۱ بخش زیادی از محبوبیت و شهرت خود را مدیون عملکرد و کارایی خود است تا جایی که خیلی از زبانهای اسکریپتنویسی دیگر برای معرفی خود از عبارت “سریع و کارا مانند لوآ” استفاده میکنند. با این حال، کارایی یکی از المانهای مهم برنامهنویسی است که هنگام کار با زبان لوآ هم باید به آن توجه کرد. « آیا عملکرد برنامهی من نیاز به بهینهسازی دارد؟ » اولین سوالی است که ذهن برنامهنویس را در خصوص بهینهسازی عملکرد به خود مشغول میکند. اگر جواب این سوال مثبت باشد سوال بعدی و کلیدی که مطرح میشود این است : « کجای برنامهی من نیاز به بهینهسازی عملکرد دارد؟ ». برای زبان لوآ، افراد متعددی روی بهبود عملکرد برنامهها و ابزارهای اندازهگیری آن تمرکز داشتهاند و با توجه به نتایج بدست آمده، نکاتی را برای بهبود عملکرد برنامههای نوشته شده با لوآ پیشنهاد می کنند. در این نوشته سعی دارم بخشی از این نکات را با شما به اشتراک بگذارم.
استفاده از متغیرهای محلی
پیشکامپایلر۲ لوآ با توجه به داشتن ثبات۳های زیاد میتواند تمام متغیرهای محلی۴ را در ثباتهای خود نگه دارد. به همین دلیل، دسترسی به متغیرهای محلی در لوآ بسیار سریع است. برای نمونه فرض کنید متغیرهای a و b محلی هستند. یک گزاره مانند a = a + b ، دستورالعمل زیر را تولید میکند:
ADD 0 0 1
حال اگر دو متغیر سراسری۵ باشند، کد برای یک عمل جمع ساده به صورت زیر خواهد بود:
GETGLOBAL 0 0 GETGLOBAL 1 1 ADD 0 0 1 SETGLOBAL 0 0
این مثال ساده نشان میدهد که چرا استفاده از متغیرهای محلی یکی از پرطرافدارترین پیشنهادات برای بهبود عملکرد برنامه است. با توجه به ساختارها و قابلیتهای زبان لوآ می توان توابع را نیز در متغیرهای محلی ذخیره نمود. اینکار نیز تاثیر خوبی در عملکرد برنامه دارد. به تکه کد زیر توجه کنید:
for i = 1, 100000 do local x = math.sin(i) end
در کد بالا ،با یک تغییر ساده و استفاده از متغیر محلی برای تابع محاسبه سینوس می توان تا ۳۰ درصد سرعت اجرا را افزایش داد:
local sin = math.sin for i = 1, 100000 do local x = sin(i) end
در هر حال ممکن است شما در کد خود به متغیرهای سراسری نیاز داشته باشید. در اینصورت حتماً هر جا که دیگر نیازی به آنها نداشتید آنها را با nil مقداردهی کنید تا به زباله۶ تبدیل شوند زیرا زباله جمعکن۷ در زبان لوآ، متغیرهای سراسری را به عنوان زباله نمیشناسد.
استفاده از دستورات کوتاه درون خطی به جای توابع هنگام کار کردن با جداول
زبان لوآ برای کار با جداول۸، توابعی را پیش بینی کرده است. یکی از این توابع، تابع insert است که برای اضافه کردن المان جدید به جدول استفاده میشود. ابزارهای اندازهگیری مختلف نشان دادهاند که استفاده دستورات کوتاه درون خطی در تعداد بالا معمولا عملکرد بهتری نسبت به تابع از پیش تعیین شده برای اضافه کردن عضو به جدول دارند زیرا دستورات درون خطی معمولاً عملگرهای زبان لوآ هستند و بار زیادی را ایجاد نمی کنند. در حالی که استفاده از تابع insert در ساده ترین حالت، نیاز به دسترسی به ماژول table و سپس فراخوانی تابع insert از این ماژول و محیط آن دارد. به دو نمونه کد زیر توجه کنید:
local a = {} local table_insert = table.insert for i = 1, 10000 do table_insert(a, i) end
local a = {} for i = 1, 10000 do a[#a+1] = i end
کد دوم، عملکرد بهتر و سریعتری نسبت به کد اول دارد. لازم به ذکر است که کد بالا را می توان با استفاده از یک عملگر سادهتر نسبت به #، به حالت بهینهتری بازنویسی کرد:
local a = {} local index = 1 for i = 1, 10000 do a[index] = i index = index + 1 end
ملاحظات در عملگر ها و توابع ریاضی
در لوآ مانند خیلی از زبانهای دیگر، برخی عملگرهای ریاضی سریعتر از عملگرهای دیگر رفتار میکنند. به عنوان مثال بهتر است که از عملگر ضرب به جای تقسیم استفاده کنیم:
x * 0.5 -- Recommended x / 2 -- Discouraged
عملگر ضرب از عمگر توان هم کاراتر است. در توانهای پایین می توان از ضرب استفاده کرد:
x * x * x -- Recommended x ^ 3 -- Discouraged
سخن آخر
تمامی پیشنهادات بالا وقتی کاربردی خواهند شد که برنامهنویس ابتدا به دو سوال اول این نوشته پیرامون بهینهسازی کد پاسخ داده باشد. قطعاْ هر برنامهای با توجه به ساختارها و شرایط ویژه خود نیازمند بهینهسازیهای خاص خود است ولی در نهایت نکات بالا به طور عمومی میتواند برنامهنویس را به سمت برنامهنویسی بهینهتر با زبان لوآ هدایت کند. نکات بالا برگرفته از کتاب الماسهای برنامهنویسی با لوآ۹ و همچنین برخی تجربیات شخصی من بوده است. شما هم اگر تجربه متفاوت یا نکات مفید دیگری در این راستا دارید، حتماً با من به اشتراک بگذارید.
۱ – Lua
۲ – Pre-Compiler
۳ – Register
۴ – Local Variables
۵ – Global Variables
۶ – Garbage
۷ – Garbage Collector
۸ – Tables
۹ – Lua Programming Gems, edited by L. H. de Figueiredo, W. Celes, R. Ierusalimschy
خیلی عالی، واقعا مختصر، مفید بود. 🙂
ممنون
خیلی مقالهی خوبی بود، مرسی
ممنون علیرضا 🙂 ساده و به درد بخور بود
راستی برای sort کردن جدولها چه روشی رو پیشنهاد میکنی؟
به نظرم بستگی به ساختار جدولی که میخواهی مرتب کنی داره. خود ماژول table یه تابع برای sort داره که فکر کنم الگوریتمش quick sort باشه و با C نوشته شده باشه ولی خب به صورت سفارشی هم میشه الگوریتم های دیگه رو پیاده کرد با توجه به ساختار جدولی که میخوای مرتب کنی.
تریک های باحالی بود.
دمت گرم
eyval alireza, kheyli khub bud.
kheyli, tamiz har headlinesh ye paragraph e mokhtasar va vaghean mofid bud.
mersi!