Bellek sınırlayıcı

Android 17 ve sonraki sürümlerde, Linux cgroup v2'yi kullanarak uygulama işlemlerinin bellek kullanımını izleyen ve sınırlayan bir sisteme ait hizmet olan bellek sınırlayıcı bulunur. Bellek sınırlayıcı, uygulamaların orantısız sistem belleği tüketmesini önleyerek genel bellek baskısını azaltır ve önemli ön plan ile önbelleğe alınmış işlemlerin agresif bir şekilde düşük bellek nedeniyle sonlandırılmasını engeller.

Mekanizma

Bellek sınırlayıcı, işlem yaşam döngüsü etkinliklerini ve durum değişikliklerini izlemek için Etkinlik Yöneticisi Hizmeti (AMS) ile entegre olur. Bellek sınırlayıcı, Linux çekirdeği cgroup v2 hiyerarşisini kullanarak bellek sınırlarını zorunlu kılar.

Bellek sınırlayıcının desteklenmesi için cihaz çekirdeğinde cgroup v2 ve memory denetleyicisi etkinleştirilmelidir. Hizmet özellikle aşağıdaki özelliklere dayanır:

memory.high
Sanal sınır. Bu sınır aşıldığında işlem kısıtlanır ve çekirdek, bu işlemden proaktif sayfa geri kazanma girişiminde bulunur.
memory.swap.max
İşlemin kullanabileceği maksimum takas alanı miktarını (ör. ZRAM) sınırlar.

Uygulamalar üzerindeki etkisi

Bellek sınırları içinde çalışan uygulamalar, bellek sınırlayıcıdan etkilenmez.

Bir uygulama memory.high sınırını aştığında çekirdek, uygulamayı sınır içinde tutmak için uygulamanın temiz dosya destekli belleğini çıkarır ve etkin olmayan anonim belleğini değiştirir. Bu sayfa çıkarma ve değiştirme etkinliği sonucunda uygulamada geçici olarak yürütme sınırlaması yaşanabilir ancak uygulama çalışmaya devam eder.

Uygulamanın takas alanı tükendikten sonra anonim bellek ayırmaya devam ettiği kontrolsüz bellek sızıntısı gibi aşırı durumlarda uygulama bellek ayıramaz ve sonlandırılır.

Süreç izleme

Bellek sınırlayıcı, varsayılan olarak uygulama işlemlerini (UID >= 10000) izler. Temel sistem kararlılığını korumak için temel sistem süreçleri muaf tutulur.

Bellek sınırlayıcı, işlemin görünürlük durumuna göre bellek sınırları atar:

  • Görünür işlemler: Kullanıcı tarafından görülebilen bir kullanıcı arayüzüne (ör. şu anda odaklanılan etkinlik veya etkin bir etkileşim) sahip işlemler. Kullanıcı arayüzünün gösterilmesi için oluşturma ve grafik ardışık düzenleri için daha büyük bir çalışma kümesi gerektiğinden görünür işlemler daha yüksek bir bellek sınırı alır.

  • Görünür olmayan işlemler: Arka planda kullanıcı arayüzü göstermeden çalışan işlemler (ör. arka plan hizmetleri veya yayın alıcılar). Kullanıcı arayüzü bileşenlerini oluşturmadıkları için daha kısıtlayıcı bir sınır altında çalışırlar.

Aşağıdaki tabloda belirli işlem durumları, bellek sınırı sınıflandırmalarıyla eşlenmiştir:

İşlem durumuBellek sınırı
PERSISTENTKısıtlanmamış
PERSISTENT_UIKısıtlanmamış
TOPGörünür
BOUND_TOPGörünür
FOREGROUND_SERVICEGörünmez
BOUND_FOREGROUND_SERVICEGörünmez
IMPORTANT_FOREGROUNDGörünür
IMPORTANT_BACKGROUNDGörünmez
TRANSIENT_BACKGROUNDGörünmez
BACKUPGörünmez
SERVICEGörünmez
RECEIVERGörünmez
TOP_SLEEPINGGörünür
HEAVY_WEIGHTGörünmez
HOMEGörünmez
LAST_ACTIVITYGörünmez
CACHED_ACTIVITYÖnbelleğe alındı
CACHED_ACTIVITY_CLIENTÖnbelleğe alındı
CACHED_RECENTÖnbelleğe alındı
CACHED_EMPTYÖnbelleğe alındı

Önbelleğe alınmış durumda işlemler dondurulur ve ardından en üst düzeyde geri kazanılır.

Bir işlem, kendisine atanan memory.high sınırını aştığında bellek sınırlayıcı bu durumu algılar ve bellek profili yakalama veya statsd'ye anormallik kaydetme gibi teşhis işlemlerini tetikleyebilir.

Yapılandırma

Android 17 ve sonraki sürümlerde, bellek sınırlayıcı, sistem bölümünde standart bir platform varsayılan yapılandırma dosyası sağlarken vendor bölümünde isteğe bağlı cihaza özel geçersiz kılmaları destekler:

  • Sistem varsayılan yapılandırması: /system/etc/memory-limiter-config.xml
  • Tedarikçi geçersiz kılma (isteğe bağlı): /vendor/etc/memory-limiter-config.xml

Bellek sınırlayıcı önce /vendor/etc/memory-limiter-config.xml olup olmadığını kontrol eder. Varsa satıcı yapılandırmasını kullanır, aksi takdirde /system/etc/memory-limiter-config.xml içindeki varsayılan sistem yapılandırmasına geri döner.

XML biçimi

Yapılandırma dosyası, memory-limiter-config.xsd içinde tanımlanan şemaya uygundur. Dosya, kullanılabilir belleğe göre sıralanmış birden fazla sınır grubu tanımlar. Hizmet, cihazın kullanılabilir RAM'ine göre en yüksek eşleşen sınır grubunu seçer. Tüm bellek değerleri mebibayt (MiB) cinsinden belirtilir.

<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
Yapılandırma sürümünü tanımlayan pozitif bir tam sayı. Bu değer 1 olmalıdır.
minimumRequiredMemTotal

Bu sınırın uygulanması için gereken minimum sistem MemTotal (MiB cinsinden). Hizmet, bunu çekirdek tarafından /proc/meminfo içinde bildirilen toplam kullanılabilir belleğe göre değerlendirir.

Bellek ayırma işlemlerini anlama: Çekirdek MemTotal değeri, donanım ve yazılım bellek ayırma işlemleri düşüldükten sonra işletim sisteminin erişebildiği fiziksel DRAM'i yansıtır. Ayrılmış alanlar, RAM'i GPU, baz bant modem, kamera ISP, güvenli yürütme ortamları ve hipervizörler gibi özel donanım bileşenleri için ayırır. Bu bileşenler genellikle 500 MiB ile 1 GiB'den fazla fiziksel bellek tüketir.

MemTotal değeri, cihazın reklamı yapılan fiziksel DRAM'den düşük olduğu için minimumRequiredMemTotal eşiklerinde bu ayrılmış alanlar için bir pay bulunur. Örneğin, 16 GB cihazları hedefleyen bir yapılandırma, 16384 (16 GB) yerine minimumRequiredMemTotal 13312 (13 GB) değerini belirtir. 12 GB cihazlar için bir katman ise 10240 (10 GB) değerini belirtir. Bu, kart düzeyindeki farklılıklar ne olursa olsun her cihazın amaçlanan katmanla eşleşmesini sağlar.

memVisible

Görünür işlemlere uygulanan MiB cinsinden geçici bellek sınırı (memory.high).

memNotVisible

Görünür olmayan işlemlere uygulanan MiB cinsinden geçici bellek sınırı (memory.high).

swapVisible

Görünür işlemlere uygulanan MiB cinsinden takas alanı sınırı (memory.swap.max).

swapNotVisible

MiB cinsinden takas alanı sınırı (memory.swap.max) görünür olmayan işlemlere uygulanır.

Standart platform sınırları

Android 17 ve sonraki sürümlerde platform, /system/etc/memory-limiter-config.xml içinde standart bellek ve takas sınırlarını ortak fiziksel RAM katmanları arasında belirtir:

Hedef fiziksel RAM Minimum gerekli
MemTotal
(minimumRequiredMemTotal)
Görünür bellek sınırı
(memVisible)
Görünür olmayan bellek sınırı
(memNotVisible)
Görünür takas limiti
(swapVisible)
Görünür olmayan takas sınırı
(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)

Bellek sınırı ilkeleri

Bellek sınırlayıcı yapılandırması aşağıdaki platform ilkelerine göre tasarlanmıştır:

  • Ekosistem tutarlılığı ve uygulama uyumluluğu: Cihazlar genelinde tutarlı bellek sınırları, Android ekosisteminde uygulama performansının tahmin edilebilir olmasını sağlar. Uygulamalar, standart bellek beklentilerine göre geliştirilir ve test edilir. Platform sınırlarının tek tip olması, beklenmedik sıklık sınırlamalarını veya erken sonlandırmaları önler.

  • Orantılı kaynak ayırma: Platform sınırları, fiziksel RAM kapasitesine göre ayarlanır:

    • Görünür işlemler: Aktif kullanıcı arayüzü, birleştirme ve oluşturma iş yüklerini desteklemek için toplam fiziksel RAM'in yaklaşık 1/2 ila 2/3'ü ayrılır.
    • Görünür olmayan işlemler: Toplam fiziksel RAM'in yaklaşık 1/4'ü ila 1/3'ü arka plan görevleri için ayrılır.
  • Evrensel uygulanabilirlik: Sınırlar, önceden yüklenmiş sistem ve OEM uygulamaları da dahil olmak üzere cihazdaki tüm uygulama süreçleri (UID >= 10000) için eşit şekilde geçerlidir. Bellek sınırlayıcı, belirli uygulamaları muaf tutmak için izin verilenler listelerini desteklemez. Bu sayede, tüm uygulamalarda adil bellek yönetimi sağlanır.

  • Çalışma zamanı sorgu API'lerinin olmaması: Android 17 ve sonraki sürümlerde uygulamalar, çalışma zamanında kendilerine atanan bellek sınırlarını programatik olarak sorgulayamaz. Standart platform sınırları, iyi davranışlı uygulamaların normal kullanım sırasında kısıtlama olmadan çalışabilmesi için geniş marjlarla tanımlanır.

  • Çekirdek geri kazanımı ve takas dinamikleri: Bir uygulama işlemi memory.highsınırına yaklaştığında Linux çekirdeği, bellek geri kazanımını özellikle bu işlem cgroup'una yönlendirir. Bu kapsamda, etkin olmayan dosya destekli sayfalar bırakılır ve soğuk anonim sayfalar ZRAM ile değiştirilir. Böylece, genel bellek yetersizliği oluşturmadan sistem akışkanlığı korunur.

Kabuk komutları

am memory-limiter komutu, geliştiricilerin ve sistem entegratörlerinin geliştirme, test ve hata ayıklama için çalışma zamanında hizmetle etkileşim kurmasına olanak tanır:

am memory-limiter <SUB-COMMAND>

durum

status alt komutu, bellek sınırlayıcının operasyonel durumunu ve etkin metriklerini bildirir:

adb shell am memory-limiter status

Örnek çıkış:

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

Çıkıştaki temel alanlar şunlardır:

monitoring
Bellek sınırlayıcının işlemleri etkin olarak izleyip izlemediğini gösterir.
visibleMem ve notVisibleMem
Her görünürlük durumu için şu anda zorunlu kılınan hesaplanmış mutlak bellek sınırları (memory.high).
visibleSwap ve notVisibleSwap
Şu anda her görünürlük durumu için uygulanan hesaplanmış mutlak takas sınırları (memory.swap.max).
events
Bir işlemin, kendisine atanan sınırı aşma sayısıdır.
processes
İzlenen işlemlerin mevcut sayısı.

yoksay

ignore alt komutu, belirli bir UID'yi veya tüm işlemleri geçici olarak bellek sınırlamasının dışında tutar. Bu, performans karşılaştırması, stres testi veya bellek davranışını teşhis etmek için yararlıdır:

# 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

manuel

manual alt komutu, belirli bir işlem için hesaplanan sınırları işlem kimliğine (PID) göre bayt cinsinden özel bir mutlak değerle geçersiz kılar. Değer bir tam sayı olmalıdır ancak MiB'yi belirtmek için MB sonekini veya GiB'yi belirtmek için GB sonekini içerebilir:

# 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

Manuel geçersiz kılmalar yalnızca söz konusu belirli süreç örneğinin ömrü boyunca geçerlidir. İşlem yeniden başlarsa durumuna göre standart sınırlara döner.

Manuel geçersiz kılma, fiziksel sistem sınırlarını aşamaz.