مصطفی میری
مصطفی میری
خواندن ۴ دقیقه·۱ سال پیش

درک Memory Leak در Angular

نشت حافظه اگر به درستی مدیریت نشود، می تواند یک مشکل جدی در برنامه های Angular باشد. این اتفاق می تواند به تدریج عملکرد برنامه را کاهش دهد، باعث crashe های غیرمنتظره شود و منابع حافظه را بیش از حد مصرف کند. در این مقاله مباحثی مثل تعریف Memory Leak ، چرا در Angular رخ می دهد، و چگونه می توان آن را شناسایی و از آن جلوگیری کرد را بررسی خواهیم کرد.

نشت حافظه (Memory Leak) چیست؟

نشت حافظه زمانی اتفاق می‌افتد که حافظه تخصیص‌یافته ،دیگر مورد نیاز نباشد اما آزاد نشود، که منجر به مصرف حافظه می‌شود که در طول زمان افزایش می‌یابد. در Angular، نشت حافظه اغلب زمانی اتفاق می‌افتد که کامپوننت ها یا سایر اشیاء به درستی حذف نمی‌شوند و از عملکرد garbage collector در بازیابی حافظه جلوگیری می‌کنند.

علل شایع Memory Leak در Angular:

الف) Subscription ها : عدم unsubscribe کردن observable ها یا event listener ها می‌تواند reference ها را زنده نگه دارد و از بین نبرد و باعث نشت حافظه شود. اطمینان حاصل کنید که subscription خود را در چرخه حیات ngOnDestroy لغو می کنید.

مثال:

private subscription: Subscription; ngOnInit() { this.subscription = someObservable.subscribe(); } ngOnDestroy() { this.subscription.unsubscribe(); }

ب) DOM Event Handlers : اتصال event handler ها به طور مستقیم به عناصر DOM بدون پاکسازی مناسب می تواند منجر به نشت حافظه شود. وقتی کامپوننت از بین رفت، event handler ها را حذف کنید.

مثال:

ngOnInit() { this.onClickHandler = this.onClick.bind(this); document.addEventListener('click', this.onClickHandler); } ngOnDestroy() { document.removeEventListener('click', this.onClickHandler); }

ج) حفظ منابع (References) : نگه داشتن منابع غیر ضروری، مانند ذخیره اشیاء در متغیرهای سراسری یا service هایی که به مدت طولانی درحال کارکرد هستند، می تواند از حذف صحیح آنها جلوگیری کند. لغو کردن آن ارجاع یا Null کردن آنها پیشنهاد می شود.

مثال:

@Injectable() export class DataService { private cachedData: any; // ... storeData(data: any) { this.cachedData = data; // از نگهداری غیر ضروری خودداری کنید } }
تشخیص Memory Leak :

برای شناسایی نشت حافظه، می‌توانید از ابزارهای مرورگر مانند Chrome DevTools استفاده کنید. استفاده از حافظه را در طول زمان کنترل کنید و به دنبال افزایش مداوم یا ناگهانی آن باشید. برای یافتن مقصران احتمالی اشیاء باقی مانده را بازرسی کنید.

ابزار Chrome DevTools چندین ویژگی را ارائه می دهد که به شناسایی نشت حافظه کمک می کند:

  • پنل حافظه (Memory panel) : استفاده از حافظه را نظارت کنید و نشت های احتمالی حافظه را در طول زمان پیگیری کنید. در inspector کروم به تب performance بروید و ضبط را شروع کنید، اکنون برخی از فعالیت ها را در وبسایت انجام دهید و سپس ضبط را متوقف کنید تا نمودار مصرف حافظه را در طول زمان مشاهده کنید.
استفاده از حافظه
استفاده از حافظه
  • عکس‌های فوری (Heap snapshots) : عکس‌های فوری از پشته جاوا اسکریپت بگیرید و آنها را برای شناسایی اشیاء باقی مانده مقایسه کنید.
عکس های فوری پشته ای - 1
عکس های فوری پشته ای - 1
عکس های فوری پشته ای - 2
عکس های فوری پشته ای - 2

همچنین می توانید هنگام انتخاب هر شی از عکس فوری بالا، لیست نگهدارنده ها را مشاهده کنید. اگر object ای را پیدا کردید که اندازه بزرگی را که انتظارش را ندارید اشغال کرد، ممکن است مشکل از آن باشد و می توانید اینجا ببینید چه مرجعی مانع از پاکسازی آن شده است.

لیست نگهدارنده ها
لیست نگهدارنده ها

شما می توانید مرجع node انتخاب شده را به دو صورت پیدا کنید.
1 - فقط موس را روی node ببرید.

شناور
شناور

2 - به سادگی 0$ را در کنسول تایپ کنید تا مرجع node انتخاب شده را دریافت کنید.

$0 را تایپ کنید
$0 را تایپ کنید
  • جدول‌های زمانی تخصیص : ایجاد شی را تجزیه و تحلیل کنید و نحوه استفاده از حافظه را درک کنید.
جدول زمانی تخصیص
جدول زمانی تخصیص
جلوگیری از Memory Leak :

الف) مدیریت چرخه حیات کامپوننت ها : اطمینان حاصل کنید که subscribe های کامپوننت ها به درستی unsubscribe می‌ شوند، event handlerها به موقع حذف می شوند و هر گونه مرجع نگه‌داشته‌شده در چرخه حیات ngOnDestroy را پاکسازی می شوند.

ngOnDestroy() { this.subscription.unsubscribe(); }

ب) از عملگرهای RxJS استفاده کنید : از عملگرهایی مانند takeUntil یا takeWhile برای unsubscribe خودکار از observable ها زمانی که یک شرط خاص برآورده می‌شود یا زمانی که کامپوننت از بین می‌رود، استفاده کنید.

مثال:

import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; private unsubscribe$: Subject<void> = new Subject<void>(); ngOnInit() { someObservable.pipe(takeUntil(this.unsubscribe$)).subscribe(); } ngOnDestroy() { this.unsubscribe$.next(); this.unsubscribe$.complete(); }

ج) تزریق وابستگی انگولار (Dependency Injection) : از DI برای مدیریت چرخه حیات سرویس ها استفاده کنید و اطمینان حاصل کنید که در صورت عدم نیاز به درستی تمیز می شوند.

مثال:

// service example @Injectable({ providedIn: 'root' }) class TestService {} }

‍‍

@Component({ … }) class TestComponent { constructor(private service: TestService) {} }

نتیجه گیری :

نشت حافظه اگر به درستی مدیریت نشود می تواند تأثیر نامطلوبی در برنامه های Angular بگذارد. با درک علل، تشخیص زودهنگام آنها و پیروی از بهترین شیوه ها برای مدیریت چرخه عمر کامپوننت ها، می توانید از نشت حافظه جلوگیری کنید و عملکرد و پایداری برنامه های Angular را بهبود دهید. به یاد داشته باشید، مدیریت فعال حافظه برای اجرای روان و کارآمد برنامه Angular شما بسیار مهم است.



این مقاله برگردان شده یک مقاله معتبر درباره این موضوع است.برای دسترسی به مقاله منبع اینجا کلیک کنید.

برای مشاهده پست های بیشتر و ارتباط با من از طریق لینکدین اینجا کلیک کنید.

امیدوارم براتون مفید واقع شده باشه.

memory leakangularbest practicesmemoryjavascript
Angular Developer
شاید از این پست‌ها خوشتان بیاید