~5 دقیقه مطالعه • بروزرسانی ۲۴ اسفند ۱۴۰۴
مقدمه
در توسعهٔ نرمافزار، اولین هدف معمولاً نوشتن کدی است که درست کار کند. اما در بسیاری از پروژهها، عملکرد (Performance) نیز اهمیت حیاتی دارد. گاهی لازم است مجموعهای از تکنیکها را به کار بگیریم تا سرعت، مصرف حافظه یا بار روی دیتابیس را بهبود دهیم، بدون اینکه رفتار برنامه تغییر کند.
رویکردهای کلی
چه چیزی را بهینه میکنید؟
Performance فقط یک معیار ندارد. ممکن است هدف شما:
- افزایش سرعت
- کاهش مصرف حافظه
- کاهش تعداد Queryها
- کاهش بار شبکه
بهبود یک بخش ممکن است به ضرر بخش دیگر باشد. مثلاً افزایش سرعت ممکن است مصرف حافظه را بالا ببرد. بنابراین باید دقیقاً بدانید چه چیزی را و چرا بهینه میکنید.
Benchmarking
حدس زدن محل مشکل کافی نیست. باید اندازهگیری کنید. ابزارهای مختلفی برای این کار وجود دارد.
ابزارهای Django
- django-debug-toolbar: نمایش Queryها، زمان اجرا، Template rendering و …
- پنلهای جانبی برای بررسی Cache و عملکرد Templateها
سرویسهای خارجی
- ابزارهای رایگان برای تحلیل سرعت صفحات از دید کاربر واقعی
- سرویسهای پولی با قابلیت پروفایلینگ عمیق و Django-aware
از ابتدا درست طراحی کنید
بخشی از بهینهسازی باید از همان ابتدا در طراحی لحاظ شود. در Python معمولاً کدی که «تمیز و درست» نوشته شده باشد، سریعتر هم هست.
کار را در سطح مناسب انجام دهید
Django چندین لایه دارد: دیتابیس، Python، Template. هرچه سطح پایینتر باشد، کار سریعتر انجام میشود.
# سریعترین: انجام کار در دیتابیس
my_bicycles.count()
# کندتر: شمارش در Python
len(my_bicycles)
# کندترین: شمارش در Template
{{ my_bicycles|length }}
همیشه مناسبترین سطح را انتخاب کنید، نه لزوماً سادهترین.
Caching
بسیاری از عملیاتها پرهزینه هستند. Cache کردن نتایج میتواند سرعت را بهطور چشمگیری افزایش دهد.
چارچوب Caching در Django
Django چند سطح Cache ارائه میدهد:
- Cache کل سایت
- Cache یک View
- Cache بخشهایی از Template
Caching جایگزین کدنویسی صحیح نیست؛ مرحلهٔ نهایی بهینهسازی است.
cached_property
اگر یک متد گرانقیمت را چند بار فراخوانی میکنید، cached_property نتیجه را ذخیره میکند تا دوباره محاسبه نشود.
درک Laziness
Laziness یعنی «محاسبه نکردن تا زمانی که لازم شود». این رویکرد مکمل Caching است.
Laziness در Python
- Generatorها
- Generator expressionها
- ارزیابی تنبل در ساختارهای مختلف
Laziness در Django
QuerySetها تنبل هستند. یعنی:
- میتوان آنها را ساخت، ترکیب کرد و پاس داد بدون اجرای Query
- فقط هنگام نیاز واقعی به داده، Query اجرا میشود
اجتناب از «ارزیابی زودهنگام» QuerySet میتواند از Queryهای غیرضروری جلوگیری کند.
keep_lazy()
این decorator باعث میشود تابعی که ورودی تنبل دارد، خودش هم تنبل بماند و فقط هنگام نیاز اجرا شود.
جمعبندی
بهینهسازی در Django مجموعهای از تکنیکهاست: از Benchmarking و انتخاب سطح مناسب برای انجام کار گرفته تا استفاده از Caching و بهرهگیری از Laziness. با شناخت این ابزارها و رفتار Django، میتوانید اپلیکیشنهایی سریعتر، سبکتر و کارآمدتر بسازید.
Database Optimization
لایهٔ پایگاهداده در Django ابزارهای زیادی برای بهینهسازی Queryها و کاهش بار دیتابیس ارائه میدهد.
مستندات بهینهسازی دیتابیس شامل نکات مهمی مانند استفاده از select_related، prefetch_related، کاهش Queryهای تکراری و تحلیل Queryها است.
Persistent Connections
فعالسازی Persistent Connections باعث میشود اتصال به دیتابیس برای چند درخواست باز بماند. این کار بهویژه در سرورهای مجازی با شبکهٔ ضعیف، سرعت را بهطور چشمگیری افزایش میدهد.
HTTP Performance
Middlewareهای مفید
ConditionalGetMiddleware
این Middleware از ETag و Last-Modified پشتیبانی میکند و باعث میشود مرورگر فقط زمانی پاسخ را دریافت کند که تغییر کرده باشد. این کار پهنای باند و زمان پاسخ را کاهش میدهد.
GZipMiddleware
پاسخها را فشرده میکند و سرعت انتقال را افزایش میدهد. اما توجه کنید که در حال حاضر یک ریسک امنیتی شناختهشده دارد و ممکن است امنیت TLS/SSL را تضعیف کند.
Sessions
Cached Sessions
استفاده از cached sessions باعث میشود دادههای سشن بهجای دیتابیس در حافظه ذخیره شوند. این کار سرعت دسترسی به سشنها را افزایش میدهد و بار دیتابیس را کاهش میدهد.
Static Files Optimization
ManifestStaticFilesStorage
این سیستم با افزودن یک هش وابسته به محتوا به نام فایلها، امکان Cache طولانیمدت فایلهای استاتیک را فراهم میکند. وقتی فایل تغییر کند، هش نیز تغییر میکند و مرورگر نسخهٔ جدید را دانلود میکند.
Minification
ابزارهای جانبی Django میتوانند HTML، CSS و JavaScript را Minify کنند. این کار شامل حذف فاصلهها، newlineها، کامنتها و کوتاهسازی نامهاست و اندازهٔ فایلها را کاهش میدهد.
Template Performance
نکات مهم
- {% block %} سریعتر از {% include %} است.
- قالبهایی که از قطعات بسیار کوچک تشکیل شدهاند، ممکن است کندتر باشند.
Cached Template Loader
فعالسازی cached template loader باعث میشود قالبها فقط یکبار کامپایل شوند و در دفعات بعدی از نسخهٔ Cache شده استفاده شود. این کار معمولاً بهبود چشمگیری ایجاد میکند.
Using Different Software Versions
گاهی نسخههای جدیدتر نرمافزارها (Django، Python یا کتابخانهها) عملکرد بهتری دارند. اما همیشه باید اندازهگیری کنید، نه اینکه فرض کنید نسخهٔ جدید سریعتر است.
نسخههای جدید معمولاً ویژگیها، امنیت و پایداری بهتری دارند، حتی اگر بهبود عملکرد اندکی داشته باشند.
Alternative Template Engines
در بیشتر پروژهها Template Engine پیشفرض Django کاملاً کافی است. اما اگر پس از بررسی دقیق مشخص شد که Bottleneck در Template Rendering است، میتوانید از جایگزینهایی مانند Jinja2 استفاده کنید که معمولاً سریعتر است.
با این حال، ابتدا باید دلیل کندی را پیدا کنید؛ شاید بتوانید همان بهبود را بدون تغییر Template Engine به دست آورید.
Alternative Python Implementations
PyPy
PyPy یک پیادهسازی سریعتر از Python است که معمولاً در برنامههای سنگین عملکرد بهتری دارد. Django با نسخههای سازگار PyPy کار میکند، اما باید سازگاری سایر کتابخانهها را نیز بررسی کنید.
C Implementations of Python Libraries
برخی کتابخانههای Python نسخههای C دارند که بسیار سریعتر هستند. اما ممکن است تفاوتهای رفتاری یا ناسازگاریهایی وجود داشته باشد.
جمعبندی
بهینهسازی در Django مجموعهای از تکنیکهاست: از بهینهسازی Queryها و استفاده از Persistent Connections گرفته تا بهبود عملکرد HTTP، استفاده از Cached Sessions، بهینهسازی فایلهای استاتیک، Template Caching و حتی بررسی نسخههای سریعتر نرمافزار. این تکنیکها زمانی بیشترین تأثیر را دارند که پروژهٔ شما از قبل اصول پایهٔ Performance را رعایت کرده باشد.
نوشته و پژوهش شده توسط دکتر شاهین صیامی