Tìm memory leaks trong app iOS với Xcode Instruments

Tram Ho

Note:

Ngày nay, có nhiều ứng dụng được đẩy lên app store, để làm cho ứng dụng của bạn nổi bật trong số đó, ứng dụng của bạn nên tiêu thụ ít bộ nhớ trong khi vẫn cung cấp trải nghiệm nhanh và tốt hơn.

Apple cung cấp những công cụ tuyệt vời với Xcode để lập profile ứng dụng cho việc tìm memory leaks và các công cụ phát hiện bug tuyệt vời khác. Hôm nay, tôi sẽ hướng dẫn bạn thông qua ví dụ nhỏ để bạn biết làm cách nào có thể phát hiện leaks trong ứng dụng.

Các bước làm

  1. Đầu tiên, download project mẫu theo link được cung cấp ở cuối bài viết để debugging leaks trong ứng dụng mẫu đó.
    Khi bạn chạy ứng dụng, bạn sẽ thấy bộ nhớ được sử dụng bởi ứng dụng tăng lên khi bạn làm theo các bước sau:

    • Vào tableview chứa list hình ảnh

    • Click vào hình ảnh để xem chi tiết

    • Quay lại tableview những hình ảnh.

    • Làm theo các bước này khoảng 30-40 lần.

Bạn có thể thấy việc sử dụng bộ nhớ của ứng dụng sẽ tăng lên liên tục.

Để theo dõi các vấn đề về bộ nhớ trong ứng dụng của bạn, bạn có thể sử dụng công cụ allocations được cung cấp bởi Apple. Hãy bắt đầu với một ứng dụng mẫu để làm quen với nó

  1. Chuẩn bị ứng dụng của bản cho việc bắt memory leaks.

Apple cung cấp một công cụ tuyệt vời gọi là instruments cho việc tìm memory leaks trong ứng dụng. Để sử dụng nó:

  • Chọn Product > Profile in your Xcode
  • Chọn Allocations trong profiler
  • Nhấn trong cửa sổ làm việc. Điều này sẽ bắt đầu ứng dụng của bạn một cách bình thường.
  1. Phân tích ứng dụng của bạn cho việc rò rỉ bộ nhớ.

Bây giờ bắt đầu sử dụng ứng dụng như bình thường. Để có được bug leaks, người dùng nên lặp lại các bước trong ứng dụng, nó sẽ khiến memory tăng cao.

Trong trường hợp của chúng tôi khi bạn qua lại SecondViewController tới DetailViewController thì memory sẽ tăng rất nhiều. Làm điều này 30 – 35 lần, sau đó click vào nút Pause.

Bạn sẽ thấy biểu đồ như hình bên dưới, nơi mà nó đang tiếp tục tăng lên. Nó có nghĩa là có một leak trong ứng dụng. Vì vậy hãy tìm nó.

Có một số điều cần ghi nhớ.

  1. Tại đây, bạn sẽ chọn vào Details > Call Trees, cái mà sẽ show cho bạn list các dòng với mức tiêu thụ bộ nhớ.

Chọn dòng với hầu hết các bytes được sử dụng. Nhìn hình bên dưới

  1. Bạn có thể thấy nhiều cuộc gọi hệ thống, ở đó có những thứ không hữu ích cho mục đích của chúng ta. Bạn nên ẩn những cuộc gọi đó từ danh sách bằng cách chọn tuỳ chọn Hiding System Libraries trong cài đặt hiển thị.

  2. Như vậy, đảm bảo rằng Record reference counts được kiểm tra, điều này sẽ hữu ích cho việc theo dõi các leaks.

Bây giờ, Call Tree sẽ show chế độ xem dạng cây với các phương thức quen thuộc bên dưới.

Bây giờ chọn dòng để đi vào chi tiết memory leaks, sẽ dẫn đến code bên trong editor có thể gây ra vẫn đề bộ nhớ . Trong trường hợp sau đây, code được hiển thị như bên dưới.

Để đảm bảo hơn, chọn Details > Statistics và tìm kiếm, DetailViewController nơi mà chúng ra đang đối mặt với vấn đề.

Như bạn thấy trong hình ảnh trên, 27 trường hợp đã được tạo ra, nhưng không có trường hợp nào released. Chọn nó để lấy list các instance cho nó.

Chọn bất kỳ trong số chúng vì tất cả đều cùng loại để theo dõi vấn đề. Khi bạn sẽ chọn bấn kì trong số chúng, nó sẽ show như màn hình bên dưới.

Hãy chắc chắn rằng bạn đã chọn Unpaired để lọc danh sách tốt hơn. Tìm dòng nơi mà thư viện có trách nhiệm được khai báo không phải là UIKit và Event type “retain” và không liên quan đến Release đã được tạo ra. Từ đó phải được Retain để Released cho mọi Responsible Caller.

Trong trường hợp của chúng tôi, nó nằm trên dòng 129 nơi mà Retain không liên quan kiểu Release. Nó trỏ đến viewDidLoad() trong DetailViewController.Vì vậy chúng ta bây giờ chúng ta chắc chắn rằng vấn đề về bộ nhớ được tạo trong viewDidLoad().

Nếu chúng ta quan sát code một cách chặt chẽ, chúng ta có thể suy luận ra chúng, biến dữ liệu đang loading file từ đường dẫn bên trong viewDidLoad(). Khi DetailViewController xuất hiện nó sẽ tự động được release.

Hãy nhìn vào dòng self.imageView.delegate = self,
Nó thật đáng nghi ngờ bởi vì chúng ta không biết cái gì mà imageView đang giữ. Đi tới class CustomImageView.

Vì vậy vấn đề ở đây là biến var delegate thuộc kiểu AnyObject? và mặc định nó là strong.

Chúng ta đang gán đối tượng DetailViewController cho delegate. Điều này đang tạo ra strong reference giữa DetailViewController và CustomImageView.

Vì CustomImageView là một con của DetailViewController, nó nên được định nghĩa là một weak vảiable để giải quyết memory leaks như một practice chung. Vì vậy hãy sửa nó lại và chạy lại ứng dụng

Khi chúng ta chạy lại ứng dụng, vấn đề của chúng ta đã được giải quyết.

Tải ứng dụng mẫu bạn vui lòng truy cập link bài viết gốc và tìm xuống dòng cuối cùng.

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo