Android 17 trở lên có Trình giới hạn bộ nhớ, một dịch vụ hệ thống 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 cgroup v2 của Linux. Trình giới hạn bộ nhớ ngăn các ứng dụng riêng lẻ tiêu thụ bộ nhớ hệ thống không cân xứng, giúp giảm áp lực tổng thể về bộ nhớ và ngăn chặn tình trạng loại bỏ các quy trình quan trọng ở nền trước và quy trình được lưu vào bộ nhớ đệm một cách quyết liệt khi bộ nhớ thấp.
Cơ chế
Memory Limiter tích hợp với Activity Manager Service (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 cách sử dụng hệ phân cấp cgroup v2 của nhân Linux.
Để hỗ trợ Trình giới hạn bộ nhớ, nhân thiết bị phải bật cgroup phiên bản 2 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á, quy trình sẽ bị điều tiết và nhân cố gắng chủ động thu hồi trang từ quy trình đó.
memory.swap.max- Giới hạn dung lượng tối đa của không gian hoán đổi (chẳng hạn như ZRAM) mà quy trình có thể sử dụng.
Tác động đến ứng dụng
Những ứng dụng hoạt động trong giới hạn bộ nhớ sẽ không bị ảnh hưởng bởi Memory Limiter.
Khi một ứng dụng vượt quá hạn mức memory.high, nhân sẽ loại bỏ bộ nhớ sạch dựa trên tệp của ứng dụng và hoán đổi bộ nhớ ẩn không hoạt động để giữ ứng dụng trong hạn mức. Do hoạt động hoán đổi và loại bỏ trang này, ứng dụng có thể gặp phải tình trạng điều tiết việc thực thi tạm thời, nhưng vẫn tiếp tục chạy.
Trong những trường hợp cực đoan (chẳng hạn như rò rỉ bộ nhớ không kiểm soát được, trong đó ứng dụng tiếp tục phân bổ bộ nhớ ẩn danh sau khi hết không gian trao đổi), ứng dụng sẽ không phân bổ được bộ nhớ và bị chấm dứt.
Giám sát quy trình
Theo mặc định, Trình giới hạn bộ nhớ sẽ giám sát các quy trình của ứng dụng (UID >= 10000). Các quy trình hệ thống cốt lõi được miễn trừ để duy trì sự ổn định cần thiết của hệ thống.
Trình giới hạn bộ nhớ sẽ chỉ định hạn mức bộ nhớ dựa trên trạng thái hiển thị của quy trình:
Các quy trình hiển thị: Các quy trình lưu trữ giao diện người dùng mà người dùng có thể thấy (chẳng hạn như hoạt động hiện đang được lấy tiêu điểm hoặc một hoạt động tương tác). Vì việc hiển thị giao diện người dùng đòi hỏi một tập hợp hoạt động lớn hơn cho các quy trình kết xuất và đồ hoạ, nên các quy trình hiển thị sẽ nhận được giới hạn bộ nhớ rộng rãi hơn.
Các quy trình không hiển thị: Các quy trình thực hiện công việc ở chế độ nền mà không hiển thị giao diện người dùng (chẳng hạn như dịch vụ nền hoặc bộ nhận tín hiệu truyền tin). Vì không kết xuất các thành phần giao diện người dùng nên các thành phần này hoạt động trong giới hạn hạn chế hơn.
Bảng sau đây liên kết các trạng thái quy trình cụ thể với các phân loại giới hạn bộ nhớ:
| Trạng thái xử lý | Hạn mức 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 vào 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, Bộ giới hạn bộ nhớ sẽ phát hiện sự kiện và có thể kích hoạt các thao tác chẩn đoán, 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
Trong Android 17 trở lên, Trình giới hạn bộ nhớ cung cấp một tệp cấu hình mặc định tiêu chuẩn của nền tảng trên phân vùng hệ thống, đồng thời hỗ trợ các chế độ ghi đè không bắt buộc dành riêng cho thiết bị trên phân vùng vendor:
- Cấu hình mặc định của hệ thống:
/system/etc/memory-limiter-config.xml - Thông tin ghi đè của nhà cung cấp (không bắt buộc):
/vendor/etc/memory-limiter-config.xml
Trước tiên, Trình giới hạn bộ nhớ sẽ kiểm tra /vendor/etc/memory-limiter-config.xml.
Nếu có, nó sẽ sử dụng cấu hình của nhà cung cấp; nếu không, nó sẽ quay lại cấu hình hệ thống mặc định trong /system/etc/memory-limiter-config.xml.
Đị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 xác định nhiều bộ giới hạn được sắp xếp theo bộ nhớ có sẵn; dịch vụ sẽ chọn bộ giới hạn phù hợp nhất dựa trên RAM có sẵn của thiết bị. Tất cả giá trị bộ nhớ đều được chỉ định bằng mebibyte (MiB).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<!-- RAM minimums account for MemTotal excluding carve-outs. -->
<limitSet>
<!-- Limits for 16GB RAM device (MemTotal >= 13GiB): 10G/5G/5G/5G -->
<minimumRequiredMemTotal>13312</minimumRequiredMemTotal>
<memVisible>10240</memVisible>
<memNotVisible>5120</memNotVisible>
<swapVisible>5120</swapVisible>
<swapNotVisible>5120</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 12GB RAM device (MemTotal >= 10GiB): 8G/4G/4G/4G -->
<minimumRequiredMemTotal>10240</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 8GB RAM device (MemTotal >= 6.5GiB): 5G/3G/3G/3G -->
<minimumRequiredMemTotal>6656</minimumRequiredMemTotal>
<memVisible>5120</memVisible>
<memNotVisible>3072</memNotVisible>
<swapVisible>3072</swapVisible>
<swapNotVisible>3072</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 6GB RAM device (MemTotal >= 4.5GiB): 4G/2G/2G/2G -->
<minimumRequiredMemTotal>4608</minimumRequiredMemTotal>
<memVisible>4096</memVisible>
<memNotVisible>2048</memNotVisible>
<swapVisible>2048</swapVisible>
<swapNotVisible>2048</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 4GB RAM device (MemTotal >= 3GiB): 2G/1G/1G/1G -->
<minimumRequiredMemTotal>3072</minimumRequiredMemTotal>
<memVisible>2048</memVisible>
<memNotVisible>1024</memNotVisible>
<swapVisible>1024</swapVisible>
<swapNotVisible>1024</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- Số nguyên dương xác định phiên bản cấu hình. Giá trị này phải là
1. minimumRequiredMemTotalDung lượng hệ thống tối thiểu
MemTotal(tính bằng MiB) cần thiết để áp dụng giới hạn này. Dịch vụ này đánh giá thông tin này dựa trên tổng bộ nhớ có sẵn mà nhân báo cáo trong/proc/meminfo.Tìm hiểu về các phân vùng bộ nhớ: Giá trị
MemTotalcủa nhân phản ánh DRAM thực mà hệ điều hành có thể truy cập sau khi trừ đi các phân vùng bộ nhớ phần cứng và phần sụn. Các phân vùng dành riêng RAM cho các thành phần phần cứng chuyên dụng như GPU, modem băng tần cơ sở, ISP camera, môi trường thực thi an toàn và trình giám sát siêu dữ liệu, thường tiêu thụ từ 500 MiB đến hơn 1 GiB bộ nhớ thực.Vì
MemTotalthấp hơn DRAM vật lý được quảng cáo của thiết bị, nên các ngưỡngminimumRequiredMemTotalbao gồm một khoảng trống cho những phần được phân bổ này. Ví dụ: cấu hình nhắm đến các thiết bị 16 GB sẽ chỉ địnhminimumRequiredMemTotallà13312(13 GiB) thay vì16384(16 GiB), còn cấp cho các thiết bị 12 GB sẽ chỉ định10240(10 GiB). Điều này đảm bảo rằng mỗi thiết bị đều phù hợp với cấp độ dự kiến, bất kể các biến thể phân vùng ở cấp độ bo mạch.memVisibleGiới hạn bộ nhớ tạm thời (
memory.high) tính bằng MiB được áp dụng cho các quy trình hiển thị.memNotVisibleGiới hạn bộ nhớ mềm (
memory.high) tính bằng MiB được áp dụng cho các quy trình không hiển thị.swapVisibleGiới hạn không gian trao đổi (
memory.swap.max) tính bằng MiB được áp dụng cho các quy trình hiển thị.swapNotVisibleGiới hạn không gian trao đổi (
memory.swap.max) tính bằng MiB được áp dụng cho các quy trình không hiển thị.
Hạn mức tiêu chuẩn của nền tảng
Trong Android 17 trở lên, nền tảng này chỉ định bộ nhớ tiêu chuẩn và các giới hạn trao đổi trong /system/etc/memory-limiter-config.xml trên các cấp RAM vật lý thông thường:
| RAM vật lý mục tiêu |
Yêu cầu tối thiểu MemTotal (minimumRequiredMemTotal) |
Giới hạn bộ nhớ hiển thị (memVisible) |
Giới hạn bộ nhớ không hiển thị (memNotVisible) |
Giới hạn hoán đổi có thể nhìn thấy (swapVisible) |
Giới hạn không hiển thị khi hoán đổi (swapNotVisible) |
|---|---|---|---|---|---|
| 16 GB | 13.312 MiB (13 GiB) | 10.240 MiB (10 GiB) | 5.120 MiB (5 GiB) | 5.120 MiB (5 GiB) | 5.120 MiB (5 GiB) |
| 12 GB | 10.240 MiB (10 GiB) | 8.192 MiB (8 GiB) | 4.096 MiB (4 GiB) | 4.096 MiB (4 GiB) | 4.096 MiB (4 GiB) |
| 8 GB | 6.656 MiB (6,5 GiB) | 5.120 MiB (5 GiB) | 3.072 MiB (3 GiB) | 3.072 MiB (3 GiB) | 3.072 MiB (3 GiB) |
| 6 GB | 4.608 MiB (4,5 GiB) | 4.096 MiB (4 GiB) | 2.048 MiB (2 GiB) | 2.048 MiB (2 GiB) | 2.048 MiB (2 GiB) |
| 4 GB | 3.072 MiB (3 GiB) | 2.048 MiB (2 GiB) | 1.024 MiB (1 GiB) | 1.024 MiB (1 GiB) | 1.024 MiB (1 GiB) |
Nguyên tắc về hạn mức bộ nhớ
Cấu hình Memory Limiter được thiết kế dựa trên các nguyên tắc sau đây của nền tảng:
Tính nhất quán của hệ sinh thái và khả năng tương thích của ứng dụng: Hạn mức bộ nhớ nhất quán trên các thiết bị đảm bảo hiệu suất ứng dụng có thể dự đoán được trong toàn bộ hệ sinh thái Android. Các ứng dụng được phát triển và kiểm thử dựa trên các kỳ vọng về bộ nhớ tiêu chuẩn; việc duy trì các hạn mức đồng nhất của nền tảng sẽ tránh được tình trạng điều tiết không mong muốn hoặc việc chấm dứt sớm.
Phân bổ tài nguyên theo tỷ lệ: Các hạn mức của nền tảng được điều chỉnh theo dung lượng RAM vật lý:
- Các quy trình hiển thị: Phân bổ khoảng 1/2 đến 2/3 tổng RAM vật lý để hỗ trợ các khối lượng công việc về giao diện người dùng, thành phần và kết xuất đang hoạt động.
- Các quy trình không hiển thị: Phân bổ khoảng 1/4 đến 1/3 tổng RAM vật lý cho các tác vụ ở chế độ nền.
Khả năng áp dụng chung: Các giới hạn được áp dụng đồng nhất cho tất cả các quy trình ứng dụng trên thiết bị (UID >= 10000), bao gồm cả các ứng dụng hệ thống và ứng dụng OEM được cài đặt sẵn. Trình giới hạn bộ nhớ không hỗ trợ danh sách cho phép để miễn trừ các ứng dụng cụ thể, đảm bảo quản lý bộ nhớ công bằng trên tất cả các ứng dụng.
Không có API truy vấn thời gian chạy: Trong Android 17 trở lên, các ứng dụng không thể truy vấn theo phương thức lập trình giới hạn bộ nhớ được chỉ định của chúng trong thời gian chạy. Các giới hạn tiêu chuẩn của nền tảng được xác định với biên độ rộng rãi để các ứng dụng hoạt động bình thường không bị hạn chế trong quá trình sử dụng thông thường.
Động lực thu hồi và hoán đổi nhân: Khi một quy trình ứng dụng sắp đạt đến giới hạn
memory.high, nhân Linux sẽ hướng việc thu hồi bộ nhớ cụ thể vào nhóm quy trình đó. Điều này bao gồm việc loại bỏ các trang không hoạt động được sao lưu bằng tệp và hoán đổi các trang ẩn danh không hoạt động sang ZRAM, duy trì tính linh hoạt của hệ thống mà không gây áp lực bộ nhớ trên toàn hệ thống.
Lệnh shell
Lệnh am memory-limiter cho phép nhà phát triển và đơn vị tích hợp hệ thống tương tác với dịch vụ trong thời gian chạy để phát triển, kiểm thử và gỡ lỗi:
am memory-limiter <SUB-COMMAND>trạng thái
Lệnh phụ status báo cáo trạng thái hoạt động và các chỉ số đang 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 đầu ra bao gồm:
monitoring- Cho biết liệu Trình giới hạn bộ nhớ có đang chủ động theo dõi các quy trình hay không.
visibleMemvànotVisibleMem- Giới hạn bộ nhớ tuyệt đối được tính toán (
memory.high) hiện được thực thi cho từng trạng thái hiển thị. visibleSwapvànotVisibleSwap- Hạn mức hoán đổi tuyệt đối được tính toán (
memory.swap.max) hiện được thực thi cho từng trạng thái hiển thị. events- Số lần một quy trình vượt quá giới hạn được chỉ định.
processes- Số lượng quy trình được giám sát hiện tại.
bỏ qua
Lệnh phụ ignore tạm thời loại trừ một UID cụ thể hoặc tất cả các quy trình khỏi việc giới hạn bộ nhớ. Điều này rất hữu ích cho việc đo điểm chuẩn hiệu suất, kiểm thử tải hoặc chẩn đoán hành vi bộ nhớ:
# Ignore a specific UID adb shell am memory-limiter ignore 10087# Ignore all processes (temporarily disables limiting) adb shell am memory-limiter ignore all# Resume normal limiting operation adb shell am memory-limiter ignore none
thủ công
Lệnh phụ manual sẽ ghi đè các giới hạn đã tính cho một quy trình cụ thể theo mã nhận dạng quy trình (PID) bằng một giá trị tuyệt đối tuỳ chỉnh tính bằng byte. Giá trị phải là một số nguyên, nhưng có thể bao gồm hậu tố MB để cho biết MiB hoặc hậu tố GB để cho biết GiB:
# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1073741824# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1024MB# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1GB# Remove the manual override for PID 1234 adb shell am memory-limiter manual 1234 none
Các chế độ ghi đè thủ công chỉ áp dụng trong suốt thời gian tồn tại của phiên bản quy trình cụ thể đó. Nếu quá trình này khởi động lại, thì quá trình này sẽ quay lại hạn mức tiêu chuẩn dựa trên trạng thái của quá trình.
Giá trị ghi đè thủ công không được vượt quá giới hạn vật lý của hệ thống.