Trong lập trình mobile, đôi khi mình tự hỏi tại sao ứng dụng của mình càng ngày càng chậm. Đôi khi còn bị crash và tần suất xuất hiện càng lúc càng nhiều hơn. Sau nhiều dự án thì mình nhận ra rằng một trong những lý do là chúng ta chỉ quan tâm đến việc code chức năng mà chưa quan tâm nhiều đến việc quản lý memory. Cho đến khi phát hiện ra rồi thì việc tìm kiếm và giải quyết nó còn khó hơn việc đập đi xây lại nhiều.
 
 
Phải chăng vì ở thời điểm hiện tại đa phần các physical device trở nên quá mạnh để chúng ta phải quan tâm tới những vấn đề về bộ nhớ. Mình nhớ nếu trở về vài năm trước, lúc RAM nó là cái gì đó quá xa xỉ, thì chúng ta phải quan tâm đến việc image load không được phép lố bao nhiêu kb, hoặc cực kì quan tâm đến app size khi mà ROM ở thời điểm đó quá thấp.

Và dưới đây là một số thông tin mình muốn chia sẻ cho bạn

Hiểu cách Memory trong flutter hoạt động

Memory layout là cách mà hệ thống quản lý bộ nhớ của máy tính sắp xếp và lưu trữ dữ liệu. Trong Flutter, một số vùng nhớ quan trọng bao gồm heap, stack và isolate. Heap là vùng nhớ được sử dụng để lưu trữ các đối tượng Flutter, trong khi stack được sử dụng để lưu trữ các biến địa phương và tham số hàm. Isolate là một khái niệm mới trong Flutter, cho phép chúng ta tạo ra nhiều tiến trình riêng biệt để xử lý tác vụ.

Memory leak, memory bloat, garbage collector

Memory leak là hiện tượng khi các đối tượng không được giải phóng sau khi sử dụng, dẫn đến tình trạng chiếm đầy bộ nhớ và làm cho ứng dụng chạy chậm hơn. Memory bloat là hiện tượng khi ứng dụng sử dụng quá nhiều bộ nhớ để lưu trữ các đối tượng, đặc biệt là trong trường hợp sử dụng các thư viện bên thứ ba. Garbage collector là một tính năng của hệ điều hành hoặc ngôn ngữ lập trình, được sử dụng để giải phóng bộ nhớ và loại bỏ các đối tượng không sử dụng.
 
5

Để tránh các vấn đề về bộ nhớ trong Flutter, cần lưu ý các điểm sau đây:

  • Hạn chế việc tạo ra quá nhiều đối tượng trong quá trình chạy ứng dụng.
  • Sử dụng hàm dispose để giải phóng các tài nguyên khi không sử dụng đối tượng nữa.
  • Sử dụng các thư viện bên thứ ba có độ tin cậy và hiệu suất tốt.
  • Tránh sử dụng các biến toàn cục quá nhiều.
  • Tránh việc lưu trữ quá nhiều dữ liệu trong các đối tượng có thể làm tăng bộ nhớ sử dụng.
// BAD: DO NOT DO THIS
// This code is leak prone:
@override
Widget build(BuildContext context) {
  final handler = () => apply(Theme.of(context));  
  useHandler(handler);
…


// GOOD
@override
Widget build(BuildContext context) {
  final theme = Theme.of(context);
  final handler = () => apply(theme);  
  useHandler(handler);
…

Để phát hiện và giải quyết Memory leak trong Flutter, bạn có thể sử dụng các công cụ và kỹ thuật sau:

  • Sử dụng Flutter DevTools để xem báo cáo về sử dụng bộ nhớ và tìm kiếm các vùng nhớ chiếm đầy.
  • Sử dụng các trình dò tìm Memory leak như leak_detector để phát hiện các đối tượng không được giải phóng.
  • Kiểm tra mã của bạn để đảm bảo rằng tất cả các đối tượng đều được giải phóng khi không còn cần sử dụng nữa.
  • Sử dụng các công cụ profiling như CPU profiler để tìm kiếm các vùng mã chạy chậm và tối ưu lại mã để giảm sử dụng bộ nhớ.

 

Ngoài ra, cần hạn chế sử dụng các tính năng có thể gây ra Memory leak như StreamSubscription hoặc Timer, và sử dụng chúng một cách cẩn thận và đúng cách. Cần lưu ý rằng các đối tượng StreamSubscription và Timer có thể tồn tại trong thời gian dài, vì vậy cần đảm bảo rằng các đối tượng này được giải phóng khi không còn sử dụng nữa.

Cuối cùng, theo mình chúng ta hãy xây dựng thói quen code tránh memory leak ngay từ bây giờ vì khi phát hiện càng sớm bao nhiều thì chúng ta sẽ càng sớm cải thiện performance ứng dụng về sau.

Tham khảo:
https://docs.flutter.dev/development/tools/devtools/memory
https://www.alibabacloud.com/blog/exploring-memory-leaks-in-flutter-from-the-rendering-process_597736