Android 17 trở lên hỗ trợ Trình giới hạn bộ nhớ (Memory Limiter), một dịch vụ hệ thống giúp giám sát và giới hạn mức sử dụng bộ nhớ của các quy trình ứng dụng bằng Linux cgroup v2. Trình giới hạn bộ nhớ ngăn các ứng dụng riêng lẻ tiêu tốn quá nhiều bộ nhớ hệ thống, giúp giảm áp lực về bộ nhớ trên toàn hệ thống và ngăn chặn việc tắt các quy trình quan trọng một cách quyết liệt do hết bộ nhớ (OOM).
Cơ chế
Trình giới hạn bộ nhớ tích hợp với Dịch vụ trình quản lý hoạt động (AMS) để theo dõi các sự kiện trong vòng đời của quy trình và các thay đổi về trạng thái. Trình giới hạn bộ nhớ thực thi các giới hạn bộ nhớ bằng hệ thống tệp cgroup v2 của kernel Linux.
Để sử dụng Trình giới hạn bộ nhớ, kernel của thiết bị phải hỗ trợ cgroup v2 và bộ điều khiển memory. Dịch vụ này đặc biệt dựa vào các thuộc tính sau:
memory.high- Giới hạn linh hoạt. Khi vượt quá giới hạn này, quy trình sẽ bị điều tiết và kernel sẽ cố gắng thu hồi bộ nhớ từ quy trình đó.
memory.swap.max- Giới hạn dung lượng không gian trao đổi mà quy trình có thể sử dụng.
Tác động đến ứng dụng
Các ứng dụng không vượt quá giới hạn bộ nhớ sẽ không bị ảnh hưởng bởi Trình giới hạn bộ nhớ.
Khi một ứng dụng vượt quá giới hạn memory.high, kernel sẽ loại bỏ bộ nhớ được sao lưu bằng tệp của ứng dụng và trao đổi bộ nhớ ẩn danh của ứng dụng đó để giữ cho ứng dụng nằm trong giới hạn. Do việc loại bỏ và trao đổi, ứng dụng có thể chạy chậm hơn.
Trong trường hợp cực đoan, nếu ứng dụng tiếp tục phân bổ bộ nhớ ẩn danh và thiết bị hết không gian trao đổi, thì ứng dụng có thể không phân bổ được bộ nhớ và do đó có khả năng gặp sự cố.
Giám sát quy trình
Theo mặc định, Trình giới hạn bộ nhớ giám sát các quy trình ứng dụng (UID >= 10000). Các quy trình hệ thống thường được miễn trừ để giúp xác minh tính ổn định của hệ thống cốt lõi.
Trình giới hạn bộ nhớ chỉ định các giới hạn bộ nhớ dựa trên trạng thái của quy trình:
Các quy trình hiển thị là các quy trình mà người dùng có thể nhận thấy, chẳng hạn như hoạt động trên nền trước, dịch vụ trên nền trước hoặc các trạng thái khác mà người dùng có thể nhận thấy hiện tượng giật.
Các quy trình không hiển thị là các quy trình chạy trên nền sau mà người dùng không tương tác hoặc không nhìn thấy.
Bảng sau đây ánh xạ các trạng thái quy trình cụ thể với các giới hạn bộ nhớ:
| Trạng thái quy trình | Giới hạn bộ nhớ |
|---|---|
PERSISTENT | Không hạn chế |
PERSISTENT_UI | Không hạn chế |
TOP | Đã hiển thị |
BOUND_TOP | Đã hiển thị |
FOREGROUND_SERVICE | Không hiển thị |
BOUND_FOREGROUND_SERVICE | Không hiển thị |
IMPORTANT_FOREGROUND | Đã hiển thị |
IMPORTANT_BACKGROUND | Không hiển thị |
TRANSIENT_BACKGROUND | Không hiển thị |
BACKUP | Không hiển thị |
SERVICE | Không hiển thị |
RECEIVER | Không hiển thị |
TOP_SLEEPING | Đã hiển thị |
HEAVY_WEIGHT | Không hiển thị |
HOME | Không hiển thị |
LAST_ACTIVITY | Không hiển thị |
CACHED_ACTIVITY | Đã lưu trong bộ nhớ đệm |
CACHED_ACTIVITY_CLIENT | Đã lưu trong bộ nhớ đệm |
CACHED_RECENT | Đã lưu trong bộ nhớ đệm |
CACHED_EMPTY | Đã lưu trong bộ nhớ đệm |
Ở trạng thái đã lưu trong bộ nhớ đệm, các quy trình sẽ bị đóng băng rồi được thu hồi tối đa.
Khi một quy trình vượt quá giới hạn memory.high được chỉ định, Trình giới hạn bộ nhớ sẽ phát hiện sự kiện này và có thể kích hoạt các hành động gỡ lỗi, chẳng hạn như ghi lại hồ sơ bộ nhớ hoặc ghi lại một điểm bất thường vào statsd.
Cấu hình
Định cấu hình Trình giới hạn bộ nhớ bằng tệp XML nằm trên phân vùng vendor. Cấu hình cho phép bạn điều chỉnh các giới hạn bộ nhớ tuyệt đối dựa trên các ràng buộc bộ nhớ cụ thể của thiết bị.
Đường dẫn tệp:
/vendor/etc/memory-limiter-config.xmlCấu hình mặc định: Nếu không tìm thấy tệp cấu hình hoặc nếu tệp đó không đọc được hoặc không hợp lệ, thì Trình giới hạn bộ nhớ sẽ bị tắt.
Định dạng XML
Tệp cấu hình tuân theo giản đồ được xác định trong memory-limiter-config.xsd. Tệp này cho phép bạn xác định nhiều tập hợp giới hạn; dịch vụ sẽ chọn tập hợp phù hợp nhất dựa trên RAM có sẵn của thiết bị. Tất cả các giá trị bộ nhớ đều được xác định theo đơn vị mebibyte (MiB).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<limitSet>
<!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- Một số nguyên dương xác định phiên bản cấu hình. Giá trị này phải là 1.
minimumRequiredMemTotal- Bộ nhớ hệ thống tối thiểu cần thiết để tập hợp giới hạn này hợp lệ.
memVisible- Giới hạn bộ nhớ (
memory.high) được phép cho các quy trình hiển thị. memNotVisible- Giới hạn bộ nhớ (
memory.high) được phép cho các quy trình không hiển thị. swapVisible- Giới hạn trao đổi (
memory.swap.max) được phép cho các quy trình hiển thị. swapNotVisible- Giới hạn trao đổi (
memory.swap.max) được phép cho các quy trình không hiển thị.
Nguyên tắc về giới hạn bộ nhớ thiết bị
Khi định cấu hình giới hạn bộ nhớ cho thiết bị, hãy cân nhắc các nguyên tắc sau:
Điều chỉnh giới hạn cho phù hợp với khả năng của phần cứng: Các OEM thiết bị có thể đặt các giới hạn phù hợp với khả năng của phần cứng thiết bị. Android đề xuất các phạm vi sau:
- Các quy trình hiển thị: Ít nhất 1/2 và nhiều nhất 2/3 tổng RAM vật lý.
- Các quy trình không hiển thị: 1/4 đến 1/3 tổng RAM vật lý. Các OEM có thể đưa ra các quyết định khác dựa trên khả năng và trường hợp sử dụng của thiết bị.
Không có API thời gian chạy cho ứng dụng: Kể từ Android 17 (SDK 37), các ứng dụng không có API để truy vấn các giới hạn bộ nhớ tại thời gian chạy. Các OEM nên cân nhắc điều này và tránh đặt giới hạn quá thấp, đảm bảo các ứng dụng không đạt đến giới hạn trong các trường hợp sử dụng hợp lý.
Cấu hình chung: Các giới hạn áp dụng cho tất cả các quy trình ứng dụng trên thiết bị, bao gồm cả các ứng dụng được cài đặt sẵn. Không có danh sách cho phép để miễn trừ một số ứng dụng khỏi các giới hạn này.
Sửa đổi cấu hình
Để thay đổi các giới hạn trên toàn hệ thống, hãy làm theo các bước sau:
- Sửa đổi
/vendor/etc/memory-limiter-config.xml. - Khởi động lại thiết bị hoặc khởi động lại
system_serverđể các thay đổi có hiệu lực.
Lệnh shell
Lệnh am memory-limiter cho phép bạn và các nhà phát triển tương tác với dịch vụ tại thời gian chạy để phát triển và kiểm thử:
am memory-limiter <SUB-COMMAND>trạng thái
Lệnh phụ status báo cáo trạng thái hoạt động của Trình giới hạn bộ nhớ:
adb shell am memory-limiter statusKết quả điểm dữ liệu:
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
Các trường chính trong kết quả bao gồm:
monitoring- Cho biết liệu trình giới hạn có đang chủ động theo dõi các quy trình hay không.
visibleMemvànotVisibleMem- Cho biết các giới hạn bộ nhớ tuyệt đối được tính toán cho từng trạng thái.
events- Số lần một quy trình vượt quá giới hạn.
processes- Số quy trình được giám sát.
bỏ qua
Lệnh phụ ignore tạm thời loại trừ một UID hoặc tất cả các quy trình khỏi việc bị giới hạn. Hành động này hữu ích cho việc kiểm thử hiệu suất hoặc khi cho phép một ứng dụng cụ thể vượt quá giới hạn.
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
thủ công
Lệnh phụ manual ghi đè các giới hạn được tính toán cho một quy trình cụ thể (theo mã quy trình hoặc PID) bằng một giá trị tuyệt đối tuỳ chỉnh tính bằng megabyte (MB):
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
Các chế độ ghi đè thủ công chỉ áp dụng cho vòng đời của quy trình. Nếu quy trình khởi động lại, quy trình đó sẽ quay lại các giới hạn mặc định dựa trên trạng thái của quy trình.