بهینه‌سازی‌ها

فصل 36- گوناگون

‎36.6‎- بهینه‌سازی‌ها

اکثر اسکریپت‌ها راه‌حل‌های سریع و چرکنویسی برای مسائل غیر پیچیده هستند. در چنین حالتی، بهینه‌سازی آنها برای سرعت بیشتر، موضوع مهمی نیست. با وجود این حالتی را در نظر بگیرید که در آن یک اسکریپت وظیفه مهمی را انجام می‌دهد، با آنکه آن را خوب انجام می‌دهد، اما به طور بسیار آهسته‌ای اجرا می‌گردد. بازنویسی نمودن آن در یک زبان ترجمه شونده ممکن است گزینه خوشایندی نباشد. ساده‌ترین اصلاح برای آن بازنویسی بخش‌هایی از اسکریپت است که آن را کند می‌کنند. آیا به کار بستن قاعده‌هایی از بهینه‌سازی کد حتی در مورد یک اسکریپت پوسته کم رتبه، امکان‌پذیر است؟

حلقه‌های داخل اسکریپت را بازبینی کنید. زمان مصرفی به سرعت به وسیله عملیات تکراری افزایش می‌یابد. اگر امکان دارد، عملیات زمانبر را از داخل حلقه‌ها حذف کنید.

استفاده از فرمان‌های builtin بر فرمان‌های سیستم ارجحیت دارد. فرمان‌های داخلی سریع‌تر اجرا می‌گردند و معمولاً موقعی که فراخوانی شوند، یک پوسته فرعی راه‌اندازی نمی‌کنند.

از فرمان‌های غیر ضروری، مخصوصاً در یک pipe پرهیز نمایید.

cat "$file" | grep "$word"

grep "$word" "$file"

# سطر فرمان‌های فوق دارای یک نتیجه یکسان هستند، اما دومی سریع‌تر
#+اجرا می‌گردد چون یک پردازش فرعی کمتر از اولی راه‌اندازی می‌کند.

بویژه گرایش به استفاده مفرط از فرمان cat در اسکریپت‌ها، مشاهده می‌گردد.


برخی عمل‌کننده‌ها، به طور در خور توجه عمل‌‌کننده expr، بسیار بی کفایت هستند و می‌‌توانند به وسیله بسط حسابی پرانتزهای دوتایی جایگزین بشوند. مثال ‎A-59‎ را ببینید.


تست‌های حساب

‎$(( ))‎ حساب از طریق 
real          0m0.294s
user          0m0.288s
sys           0m0.008s

expr: حساب به وسیله
real          1m17.879s   # خیلی کندتر!
user          0m3.600s
sys           0m8.765s

let: حساب به وسیله
real          0m0.364s
user          0m0.372s
sys           0m0.000s

ساختارهای بررسی شرط در اسکریپت‌ها، سزاوار موشکافی عمیق هستند. برای به حداقل رساندن زمان اجرای اسکریپت، case را جایگزین ساختارهای ‎if-then‎ نمایید و موقعی که امکان دارد، تست‌ها را ترکیب کنید. یک بار دیگر به مثال ‎A-59‎ مراجعه کنید.


 "case" : تست با کاربرد ساختار
real          0m0.329s
user          0m0.320s
sys           0m0.000s


بدون نقل‌قول‌ها ‎if []‎ تست با
real          0m0.438s
user          0m0.432s
sys           0m0.008s


با نقل‌قول‌ها ‎if []‎ تست با
real          0m0.476s
user          0m0.452s
sys           0m0.024s


 -eq با کاربرد ‎if []‎ تست با
real          0m0.457s
user          0m0.456s
sys           0m0.000s


‎Erik Brandsberg‎ پیشنهاد می‌کند، در اکثر موارد استفاده از آرایه‌های انجمنی نسبت به آرایه‌های دارای شاخص عددی ترجیح داده شود. موقع رونویسی کمیت‌ها، در یک آرایه عددی، برعکس آرایه‌های انجمنی یک امتیاز منفی قابل توجهی در عملکرد وجود دارد. اجرای یک اسکریپت تست این مورد را تایید می‌کند. مثال ‎A-60‎ را ببینید.


      تست‌های انتساب

                            تخصیص یک متغیر ساده
real          0m0.418s
user          0m0.416s
sys           0m0.004s

             تخصیص یک عضو آرایه دارای شاخص‌ عددی
real          0m0.582s
user          0m0.564s
sys           0m0.016s

                 رونویسی یک عضو آرایه شاخص عددی
real          0m21.931s
user          0m21.913s
sys           0m0.016s

               خواندن خطی آرایه دارای شاخص عددی
real          0m0.422s
user          0m0.416s
sys           0m0.004s

                     تخصیص یک مدخل آرایه انجمنی
real          0m1.800s
user          0m1.796s
sys           0m0.004s

                رونویسی یک مدخل از آرایه انجمنی
real          0m1.798s
user          0m1.784s
sys           0m0.012s

                خواندن خطی یک مدخل آرایه انجمنی
real          0m0.420s
user          0m0.420s
sys           0m0.000s

           تخصیص یک عدد تصادفی به یک متغیر ساده
real          0m0.402s
user          0m0.388s
sys           0m0.016s

تخصیص یک مدخل آرایه عددی پراکنده به واحدهای ‎64k‎
real          0m12.678s
user          0m12.649s
sys           0m0.028s

      خواندن مدخل آرایه پراکنده دارای شاخص عددی
real          0m0.087s
user          0m0.084s
sys           0m0.000s

 تخصیص مدخل آرایه انجمنی پراکنده به واحدهای ‎64k‎
real          0m0.698s
user          0m0.696s
sys           0m0.004s

               خواندن مدخل آرایه انجمنی پراکنده
real          0m0.083s
user          0m0.084s
sys           0m0.000s

از ابزارهای time و times برای نمایش نموداری فرمان‌هایی که محاسبات زیادی را شامل می‌شوند استفاده کنید. بازنویسی بخش‌های بسیار زمانبر کد را در C یا حتی در یک اسمبلر مورد مطالعه قرار بدهید.

برای حداقل سازی ورودی-خروجی فایل تلاش کنید. Bash به ویژه در مدیریت فایل‌ها با کفایت نیست، بنابراین استفاده از ابزارهای مناسب‌تری جهت این مورد، از قبیل awk یا Perl را در داخل اسکریپت‌ها در نظر بگیرید.

اسکریپت‌هایتان را در یک شکل پیمانه‌ای و بهم پیوسته ‎[1]‎ بنویسید، طوری که در صورت لزوم بتوانند تجدید سازمان و فشرده بشوند. برخی تکنیک‌های بهینه‌سازی قابل اعمال در زبان‌های سطح بالا ممکن است برای اسکریپت‌ها نیز کار کنند، اما برخی دیگر از قبیل loop unrolling، اساسا نامربوط هستند. بالاتر از همه، عقل سلیم را به کار ببرید.

برای یک نمایش تجربی عالی از اینکه بهینه‌سازی چگونه می‌تواند به طور چشمگیری زمان اجرای یک اسکریپت را کاهش بدهد، مثال ‎16-47‎ را ملاحظه کنید.

یادداشت‌ها

[1]

این به طور معمول به معنی استفاده وافر از توابع است.