Quản lý RAM trên Android là một trong những khía cạnh bị hiểu lầm nhiều nhất. Trái ngược với suy nghĩ thông thường rằng "càng nhiều RAM trống càng tốt", Android hoạt động dựa trên một triết lý hoàn toàn khác: "bộ nhớ trống là bộ nhớ lãng phí". Thay vì vội vàng giải phóng RAM ngay sau khi người dùng đóng một ứng dụng, Android cố gắng giữ lại tiến trình của ứng dụng đó trong bộ nhớ.
Mục đích là để khi người dùng muốn mở lại hoặc chuyển đổi qua lại giữa các ứng dụng, quá trình này sẽ diễn ra gần như tức thì, thay vì phải tải lại mọi thứ từ bộ nhớ lưu trữ chậm hơn. Trong bài viết này xin chia sẻ cách mà hệ điều hành Android quản lý bộ nhớ trên các thiết bị di động.

Thiết bị Android chứa ba loại bộ nhớ khác nhau: RAM, zRAM và bộ nhớ lưu trữ:
- RAM là loại bộ nhớ nhanh nhất, nhưng thường bị giới hạn về dung lượng. Các thiết bị cao cấp thường có dung lượng RAM lớn nhất.
- zRAM là một phân vùng RAM được dùng để hoán đổi (swap). Mọi thứ đều được nén lại khi đặt vào zRAM, sau đó được giải nén khi “được lấy” khỏi zRAM. Phân vùng RAM này tăng hoặc giảm dung lượng khi các trang được di chuyển vào hoặc ra khỏi zRAM. Các nhà sản xuất thiết bị có thể đặt kích thước tối đa cho nó.
- Bộ nhớ lưu trữ chứa tất cả dữ liệu cố định, chẳng hạn như hệ thống tệp và mã đối tượng đi kèm cho tất cả ứng dụng, thư viện và nền tảng. Bộ nhớ lưu trữ có dung lượng lớn hơn nhiều so với 2 loại bộ nhớ còn lại kia. Trên Android, dung lượng lưu trữ không được dùng cho việc hoán đổi không gian như các phương thức triển khai khác trên hệ điều hành Linux, vì việc ghi thường xuyên có thể làm chậm và giảm thời gian sử dụng phương tiện lưu trữ.
Về mặt kỹ thuật, RAM được hệ điều hành quản lý dưới dạng các khối nhỏ gọi là "pages", thường có kích thước 4 KB. Các trang này được phân thành hai loại chính:
- File-backed pages: Các page chứa dữ liệu được ánh xạ từ một tệp trên bộ nhớ lưu trữ, ví dụ như mã thực thi của một ứng dụng. Nếu trang này chưa bị sửa đổi ("clean"), nó có thể được giải phóng một cách an toàn vì hệ thống luôn có thể đọc lại từ tệp gốc. Nếu nó đã bị sửa đổi ("dirty"), nội dung mới phải được xử lý trước khi giải phóng.
- Anonymous pages: Các page không được sao lưu bởi bất kỳ tệp nào. Chúng chứa dữ liệu được tạo ra trong quá trình chạy ứng dụng, chẳng hạn như vùng nhớ heap và stack. Việc giải phóng các trang này phức tạp hơn vì dữ liệu của chúng không tồn tại ở nơi nào khác.
Vì hầu hết các ứng dụng Android được viết bằng Java hoặc Kotlin và chạy trên môi trường Android Runtime (ART), việc quản lý bộ nhớ heap (Android memory heap) được thực hiện tự động thông qua một quy trình gọi là “Thu gom rác” (Garbage Collection - GC).
GC có nhiệm vụ tự động tìm kiếm và giải phóng các đối tượng trong bộ nhớ mà ứng dụng không còn sử dụng. Android sử dụng một thuật toán GC được phân theo 3 "thế hệ" (Young, Old và Permanent), dựa trên thời gian tồn tại và kích thước của đối tượng. Mỗi "thế hệ" sẽ có kích thước giới hạn bộ nhớ riêng, khi bộ nhớ đó đầy, GC sẽ hoạt động để giải phóng.
Để tối ưu hóa hơn nữa việc sử dụng RAM, Android sử dụng rộng rãi các kỹ thuật chia sẻ bộ nhớ. Kỹ thuật quan trọng nhất là Zygote. Khi hệ thống khởi động, một tiến trình đặc biệt tên là Zygote sẽ được tạo ra. Zygote tải trước tất cả các lớp, tài nguyên và thư viện cốt lõi của framework Android. Khi bạn khởi chạy một ứng dụng mới, thay vì tạo một tiến trình hoàn toàn mới từ đầu, hệ thống chỉ cần "phân nhánh" (fork) từ tiến trình Zygote.
Tiến trình con mới này sẽ kế thừa tất cả các tài nguyên đã được tải sẵn và chỉ cần tải thêm mã nguồn riêng của ứng dụng đó. Cơ chế này cho phép hàng trăm megabyte RAM chứa mã framework được chia sẻ hiệu quả giữa tất cả các ứng dụng đang chạy, tiết kiệm một lượng lớn bộ nhớ.
Mặc dù có các cơ chế tối ưu, dung lượng RAM vẫn là hữu hạn. Khi bộ nhớ trống bắt đầu cạn kiệt, Android sẽ kích hoạt một chuỗi các cơ chế để giải phóng không gian.
Đầu tiên là Kernel Swap Daemon (kswapd), một tiến trình của nhân Linux. Khi bộ nhớ trống giảm xuống dưới một ngưỡng nhất định, kswapd sẽ bắt đầu hoạt động. Nó cố gắng giải phóng bộ nhớ bằng cách loại bỏ các "clean pages", vì chúng có thể được tải lại từ bộ nhớ lưu trữ khi cần. Đối với các "dirty pages" và các trang khác, thay vì loại bỏ ngay, kswapd sẽ nén chúng và chuyển vào zRAM.
Các quy trình của Android, với điểm cao ở trên cùng và điểm thấp ở dưới cùng.
Nếu kswapd không thể giải phóng đủ bộ nhớ để đáp ứng nhu cầu, cơ chế cuối cùng và "bạo lực" nhất sẽ được kích hoạt: Low Memory Killer Daemon (lmkd). lmkd là một "daemon" chịu trách nhiệm "kill" các tiến trình để giải phóng RAM, đảm bảo rằng các tiến trình quan trọng nhất (ví dụ ứng dụng foreground)luôn có đủ bộ nhớ để hoạt động. Quá trình này không diễn ra ngẫu nhiên. lmkd sử dụng một điểm số gọi là "oom_adj_score" để xác định mức độ ưu tiên của mỗi tiến trình. Các tiến trình có điểm số cao nhất (ít quan trọng nhất, như các tiến trình rỗng hoặc tiến trình nền đã không được sử dụng trong một thời gian dài) sẽ bị "kill" trước tiên.
Trong quá trình phát triển, lmkd đã có một sự tiến hóa quan trọng. Ban đầu, nó là một driver nằm trong nhân Linux, hoạt động dựa trên các ngưỡng bộ nhớ trống cố định, khá cứng nhắc và khó tùy chỉnh. Các phiên bản Android gần đây đã chuyển nó thành một daemon chạy ở không gian người dùng (userspace), giúp nó trở nên linh hoạt và dễ cập nhật hơn thông qua các bản cập nhật hệ thống thông thường.
Sự thay đổi này không chỉ là về vị trí mà nó còn đại diện cho một cuộc cách mạng thầm lặng trong cách Android nhận biết áp lực bộ nhớ (memory pressure). Thay vì chỉ dựa vào các con số trừu tượng như lượng RAM trống, lmkd hiện đại sử dụng một cơ chế tinh vi hơn từ nhân Linux gọi là Pressure Stall Information (PSI). PSI không trả lời câu hỏi "Còn bao nhiêu RAM?", mà trả lời câu hỏi "Các ứng dụng có đang phải chờ đợi vì thiếu RAM không?".
Nó đo lường thời gian mà các tác vụ bị "đứng" (stalled) do tranh chấp tài nguyên bộ nhớ. Đây là một chỉ số trực tiếp về tác động của tình trạng thiếu bộ nhớ đến trải nghiệm người dùng. Bằng cách sử dụng PSI, lmkd có thể đưa ra quyết định "kill" tiến trình một cách thông minh hơn nhiều, chỉ can thiệp khi áp lực bộ nhớ thực sự bắt đầu ảnh hưởng đến hiệu suất hệ thống.
Ngoài ra, lmkd còn có khả năng phát hiện hiện tượng "thrashing" (khi hệ thống liên tục hoán đổi các page bộ nhớ vào và ra, gây tốn tài nguyên mà không hiệu quả), từ đó đưa ra quyết định chính xác hơn.
Như đã đề cập, Android không sử dụng bộ nhớ lưu trữ vật lý (bộ nhớ trong) làm không gian hoán đổi (swap) như các hệ điều hành máy tính để bàn. Lý do chính là vì bộ nhớ flash (eMMC, UFS) có số chu kỳ ghi/xóa giới hạn. Việc hoán đổi liên tục sẽ làm giảm đáng kể tuổi thọ của chip nhớ.
Thay vào đó, Android sử dụng zRAM. Đây là một khối bộ nhớ được tạo ra bên trong chính RAM vật lý, hoạt động như một "thiết bị" hoán đổi ảo. Khi hệ thống cần giải phóng bộ nhớ, thay vì loại bỏ hoàn toàn các trang bộ nhớ của một ứng dụng nền, kswapd sẽ nén các trang đó và lưu chúng vào zRAM.
zRAM là một giải pháp cân bằng cho bài toán đa nhiệm trên điện thoại di động. Thiết bị di động có lượng RAM hạn chế, nhưng người dùng lại mong muốn chuyển đổi ứng dụng nhanh chóng. Việc "kill" ứng dụng ngay khi thoát sẽ làm chậm trải nghiệm, trong khi việc giữ tất cả trong RAM là không thể. zRAM đã giải quyết vấn đề này bằng cách hy sinh một phần nhỏ tài nguyên CPU (để nén/giải nén) và một phần RAM vật lý để tạo ra một "bộ nhớ đệm" nén. Điều này cho phép hệ thống tạo ra ảo giác có nhiều RAM hơn thực tế, giúp giữ nhiều ứng dụng "sống" hơn.
Để đảm bảo quá trình này diễn ra nhanh chóng, Android thường sử dụng các thuật toán nén được tối ưu hóa cho tốc độ, đặc biệt là tốc độ giải nén. LZ4 là một lựa chọn phổ biến, nổi bật với khả năng giải nén cực nhanh, đạt tốc độ hàng gigabyte mỗi giây. Việc ưu tiên tốc độ giải nén là hoàn toàn hợp lý, vì khi người dùng quay trở lại một ứng dụng đã bị nén vào zRAM, dữ liệu của nó phải được giải nén và đưa trở lại RAM một cách nhanh nhất có thể để tránh gây ra độ trễ có thể nhận thấy.
Tất nhiên, zRAM không phải là không có sự đánh đổi. Quá trình nén và giải nén sẽ ảnh hưởng đến hiệu năng CPU. Mặc dù là nhanh hơn rất nhiều so với việc đọc từ bộ nhớ lưu trữ, việc truy cập dữ liệu từ zRAM vẫn có một độ trễ nhỏ so với việc truy cập trực tiếp từ RAM. Một số nhà sản xuất còn triển khai tính năng "RAM ảo" hay "RAM mở rộng" bằng cách tạo một tệp hoán đổi trên bộ nhớ trong, hoạt động như một zRAM bổ sung. Mặc dù giúp giữ nhiều ứng dụng hơn nữa, giải pháp này phải chịu độ trễ cao hơn đáng kể và có thể ảnh hưởng đến tuổi thọ của bộ nhớ trong.
![[IMG]](https://photo2.tinhte.vn/data/attachment-files/2022/03/5914102_cover_SK-Hynix.jpeg)
RAM của điện thoại giống như mặt bàn làm việc của bạn, còn bộ nhớ trong (nơi chứa ứng dụng, ảnh, video) là một cái tủ khổng lồ, nó sẽ tương tự như thế này:
- Mở ứng dụng từ đầu: Giống như việc bạn phải chạy xuống tủ kho, tìm đúng món đồ, rồi mang lên bàn để sử dụng. Quá trình này tốn thời gian.
- Mở lại ứng dụng đã có sẵn trong RAM: Giống như món đồ đó đã được bày sẵn trên bàn làm việc. Bạn chỉ cần quay ra và dùng ngay lập tức.
Android luôn cố gắng giữ các ứng dụng bạn thường dùng trên "mặt bàn" RAM để khi bạn cần, chúng sẵn sàng ngay tức thì. Đó là lý do tại sao bạn không cần phải lo lắng khi thấy cột RAM báo gần đầy.
zRAM sẽ như một chiếc túi đặt trên bàn làm việc của bạn. Khi mặt bàn bắt đầu chật, thay vì vứt bớt đồ đi, Android sẽ lấy những món đồ ít dùng, cho vào "túi hút chân không" (nén chúng lại) và đặt gọn vào một góc của mặt bàn (zRAM). Món đồ vẫn ở trên bàn, chỉ là được nén nhỏ lại. Khi bạn cần dùng, Android sẽ "mở túi" (giải nén) rất nhanh.
Nhưng dù tối ưu đến đâu, "mặt bàn" RAM vẫn có giới hạn. Khi nó bắt đầu quá tải, Android sẽ hành động theo từng bước, từ nhẹ nhàng đến mạnh tay:
- Khi bộ nhớ bắt đầu cạn, một tiến trình tên là kswapd sẽ ra tay, nó sẽ tìm những thứ có thể dọn đi mà không ảnh hưởng gì, với những ứng dụng nền bạn ít dùng tới, nó sẽ nén chúng lại và cho vào "túi hút chân không" zRAM để tiết kiệm diện tích.
- Nếu sau khi dọn dẹp mà vẫn không đủ chỗ, lmkd sẽ xuất hiện. Nhiệm vụ của nó là "mời" một vài ứng dụng ra khỏi "bàn làm việc" (tắt tiến trình) để lấy lại không gian cho những việc quan trọng hơn.
Quá trình này không hề ngẫu nhiên, lmkd có một danh sách ưu tiên rất rõ ràng:
- VIP: Ứng dụng bạn đang dùng trên màn hình sẽ được bảo vệ tuyệt đối.
- Danh sách "mời ra ngoài": Các ứng dụng chạy nền mà bạn đã không dùng từ rất lâu sẽ bị đóng trước tiên.
Hệ thống quản lý RAM của Android cực kỳ phức tạp và thông minh, được thiết kế để tối ưu cho trải nghiệm người dùng. Lần tới, khi thấy điện thoại của mình chỉ còn ít RAM trống, bạn hãy yên tâm rằng đó là dấu hiệu hệ điều hành đang làm rất tốt công việc của nó là giữ mọi thứ sẵn sàng cho bạn.