메모리 리미터

Android 17 및 이후 버전은 Linux cgroup v2를 사용하여 애플리케이션 프로세스의 메모리 사용량을 모니터링하고 제한하는 시스템 서비스인 메모리 제한 도구를 지원합니다. 메모리 제한 도구는 개별 앱이 과도한 시스템 메모리를 소비하지 못하도록 하여 시스템 전체의 메모리 압박을 줄이고 중요한 프로세스의 공격적인 메모리 부족 (OOM) 종료를 방지합니다.

메커니즘

메모리 제한 도구는 활동 관리자 서비스 (AMS)와 통합되어 프로세스 수명 주기 이벤트와 상태 변경을 추적합니다. 메모리 제한 도구는 Linux 커널 cgroup v2 파일 시스템을 사용하여 메모리 한도를 적용합니다.

메모리 제한 도구를 사용하려면 기기 커널이 cgroup v2 및 memory 컨트롤러를 지원해야 합니다. 이 서비스는 특히 다음 속성에 의존합니다.

memory.high
소프트 한도입니다. 이 한도를 초과하면 프로세스가 제한되고 커널이 프로세스에서 메모리를 회수하려고 시도합니다.
memory.swap.max
프로세스에서 사용할 수 있는 스왑 공간의 양을 제한합니다.

앱에 미치는 영향

메모리 한도를 초과하지 않는 앱은 메모리 제한 도구의 영향을 받지 않습니다.

앱이 memory.high 한도를 초과하면 커널은 앱의 파일 지원 메모리를 삭제하고 익명 메모리를 스왑하여 앱을 한도 내에 유지합니다. 삭제 및 스왑으로 인해 앱이 더 느리게 실행될 수 있습니다.

극단적으로 앱이 익명 메모리를 계속 할당하고 기기의 스왑 공간이 부족하면 앱이 메모리를 할당하지 못할 수 있으며 그 결과 비정상 종료될 가능성이 높습니다.

프로세스 모니터링

메모리 제한 도구는 기본적으로 앱 프로세스 (UID >= 10000)를 모니터링합니다. 시스템 프로세스는 일반적으로 핵심 시스템 안정성을 확인하는 데 도움이 되도록 제외됩니다.

메모리 제한 도구는 프로세스 상태에 따라 메모리 한도를 할당합니다.

  • 표시되는 프로세스 는 포그라운드 활동, 포그라운드 서비스 또는 기타 끊김이 감지되는 상태와 같이 사용자가 인식할 수 있는 프로세스입니다.

  • 표시되지 않는 프로세스 는 사용자와 상호작용하지 않거나 사용자에게 표시되지 않는 백그라운드 프로세스입니다.

다음 표에서는 특정 프로세스 상태를 메모리 한도에 매핑합니다.

프로세스 상태메모리 한도
PERSISTENT제한 없음
PERSISTENT_UI제한 없음
TOP표시
BOUND_TOP표시
FOREGROUND_SERVICE표시 안함
BOUND_FOREGROUND_SERVICE표시 안함
IMPORTANT_FOREGROUND표시
IMPORTANT_BACKGROUND표시 안함
TRANSIENT_BACKGROUND표시 안함
BACKUP표시 안함
SERVICE표시 안함
RECEIVER표시 안함
TOP_SLEEPING표시
HEAVY_WEIGHT표시 안함
HOME표시 안함
LAST_ACTIVITY표시 안함
CACHED_ACTIVITY캐시됨
CACHED_ACTIVITY_CLIENT캐시됨
CACHED_RECENT캐시됨
CACHED_EMPTY캐시됨

캐시된 상태에서 프로세스는 고정된 후 최대한 회수됩니다.

프로세스가 할당된 memory.high 한도를 초과하면 메모리 제한 도구가 이벤트를 감지하고 메모리 프로필 캡처 또는 statsd에 비정상 로깅과 같은 디버깅 작업을 트리거할 수 있습니다.

구성

vendor 파티션에 있는 XML 파일을 사용하여 메모리 제한 도구를 구성합니다. 구성을 사용하면 기기의 특정 메모리 제약조건에 따라 절대 메모리 한도를 조정할 수 있습니다.

  • 파일 경로: /vendor/etc/memory-limiter-config.xml

  • 기본 구성: 구성 파일을 찾을 수 없거나 읽을 수 없거나 잘못된 경우 메모리 제한 도구가 사용 중지됩니다.

XML 형식

구성 파일은 memory-limiter-config.xsd에 정의된 스키마를 따릅니다. 이 파일을 사용하면 여러 한도 세트를 정의할 수 있습니다. 서비스는 기기의 사용 가능한 RAM을 기반으로 가장 적합한 세트를 선택합니다. 모든 메모리 값은 메비바이트 (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
구성 버전을 식별하는 양의 정수입니다. 1이어야 합니다.
minimumRequiredMemTotal
이 한도 세트가 유효하려면 필요한 최소 사용 가능한 시스템 메모리입니다.
memVisible
표시되는 프로세스에 허용되는 메모리 한도 (memory.high)입니다.
memNotVisible
표시되지 않는 프로세스에 허용되는 메모리 한도 (memory.high)입니다.
swapVisible
표시되는 프로세스에 허용되는 스왑 한도 (memory.swap.max)입니다.
swapNotVisible
표시되지 않는 프로세스에 허용되는 스왑 한도 (memory.swap.max)입니다.

구성 수정

시스템 전체 한도를 변경하려면 다음 단계를 따르세요.

  1. /vendor/etc/memory-limiter-config.xml을 수정합니다.
  2. 변경사항을 적용하려면 기기를 재부팅하거나 system_server를 다시 시작합니다.

셸 명령어

am memory-limiter 명령어를 사용하면 개발 및 테스트를 위해 런타임에 서비스와 상호작용할 수 있습니다.

am memory-limiter <SUB-COMMAND>

상태

status 하위 명령어는 메모리 제한 도구의 작동 상태를 보고합니다.

adb shell am memory-limiter status

출력 예시:

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

출력의 주요 필드는 다음과 같습니다.

monitoring
제한 도구가 프로세스를 적극적으로 감시하는지 여부를 나타냅니다.
visibleMemnotVisibleMem
각 상태의 계산된 절대 메모리 한도를 나타냅니다.
events
프로세스가 한도를 초과한 횟수입니다.
processes
모니터링되는 프로세스 수입니다.

무시

ignore 하위 명령어는 제한에서 UID 또는 모든 프로세스를 일시적으로 제외합니다. 이 작업은 성능 테스트를 하거나 특정 앱이 한도를 초과하도록 허용할 때 유용합니다.

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

수동

manual 하위 명령어는 특정 프로세스(프로세스 ID 또는 PID별)의 계산된 한도를 메가바이트 (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

수동 재정의는 프로세스의 수명 주기에만 적용됩니다. 프로세스가 다시 시작되면 상태에 따라 기본 한도로 돌아갑니다.