Trình giới hạn bộ nhớ

Android 17 trở lên hỗ trợ bộ giới hạn bộ nhớ. Đây là 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. Bộ 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 bộ nhớ trên toàn hệ thống và ngăn chặn việc loại bỏ các quy trình quan trọng một cách quyết liệt do hết bộ nhớ (OOM).

Cơ chế

Bộ 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. Bộ 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 Bộ 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á, 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 Bộ 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ữ ứng dụng 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, Bộ giới hạn bộ nhớ sẽ 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.

Bộ 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 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 giới hạn bộ nhớ:

Trạng thái quy trìnhGiới hạn bộ nhớ
PERSISTENTKhông hạn chế
PERSISTENT_UIKhông hạn chế
TOPĐã hiển thị
BOUND_TOPĐã hiển thị
FOREGROUND_SERVICEKhông hiển thị
BOUND_FOREGROUND_SERVICEKhông hiển thị
IMPORTANT_FOREGROUNDĐã hiển thị
IMPORTANT_BACKGROUNDKhông hiển thị
TRANSIENT_BACKGROUNDKhông hiển thị
BACKUPKhông hiển thị
SERVICEKhông hiển thị
RECEIVERKhông hiển thị
TOP_SLEEPINGĐã hiển thị
HEAVY_WEIGHTKhông hiển thị
HOMEKhông hiển thị
LAST_ACTIVITYKhô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 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 Bộ 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.xml

  • Cấ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ì Bộ 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 bộ giới hạn; dịch vụ sẽ chọn bộ phù hợp nhất dựa trên RAM hiện có của thiết bị. Tất 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 để bộ 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ị.

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:

  1. Sửa đổi /vendor/etc/memory-limiter-config.xml.
  2. 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à nhà phát triển tương tác với dịch vụ trong 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 Bộ giới hạn bộ nhớ:

adb shell am memory-limiter status

Kế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 bộ giới hạn có đang chủ động theo dõi các quy trình hay không.
visibleMemnotVisibleMem
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 UID
adb 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 1234
adb 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.