Bu bellek sorununu zarif bir şekilde nasıl çözebilirim?


10

Takas bölümü olan standart bir Linux (Debian testi) dizüstü bilgisayarım var.

Bununla bir çok deney yapıyorum. Bazıları gerçekten hafızaya aç ve Linux'un varsayılan olarak davranışı benim için bir sorun ... Aptal bir örnek verelim:

  1. Dizüstü bilgisayarın önünde oturun
  2. Bir terminal açın
  3. Tür pythonsonra,a = [0]*100000000

Şimdi bu büyük listeyi işlemek için yeterli RAM'iniz olmayacak. Linux RAM'i dolduracak, sonra takas edecek ve birkaç dakika sonra OOM katili tetiklenecek ve (neredeyse) rastgele hizmetleri öldürecek ve umarım eğer Ctrl + C'ye zamanında pythonbasarsanız ve terminal hala odaklanıyordu, bilgisayar tekrar tepki verecek.

Bu istenmeyen takastan kaçınmak ve (RAM'de) sahip olduğumdan daha fazla bellek ayırma hakkını reddetmek için bazı bellek sınırlarını zorlamak istiyorum. Bellek talebi belirli bir sınırın altındaysa veya root tarafından sorulursa, root dışında herhangi bir kullanıcının en fazla bellek aç işlemini öldürün.

ulimit -Sv [mem] Arkadan duydum!

Ho Ho! "Kullanım cgroupsaracılığı cgexec!" birisi ilk sırada diyor!

Evet, haklısınız: bunlar gerçekten çok iyi çözümlerdir. Fakat:

  • Sistem çapında uygulanmazlar
  • İşlem başına limitler belirlenir
  • Sınırlar statiktir, gerçek miktar boş bir RAM (AFAIK) dikkate alınmaz
  • Burada ve orada , bunların zor sınırları zorlamak için gerçekten iyi bir çözüm olmadığını söylüyorlar.

Ne istiyorum ki çekirdek şöyle diyor: "Kullanıcı foo'ya (root değil) aitsiniz , çok fazla bellek kullanıyorsunuz ve hafızamız tükenecek. Üzgünüm ahbap ... şimdi öl!"

Veya: "Sen ne yapıyorsun? X MB'ye ihtiyacın var ve sadece y MB kullanılabilir. Evet, SWAP boş, ama kirli işini yapmak için SWAP'ı kullanmak istemiyorsun, değil mi? Hayır, ben Hayır dedi! Senin için hafıza yok! Eğer ısrar edersen öleceksin! "


2
Bu makalede , OOM katilinin doğru işlemi seçmesine yardımcı olan bir algoritma zaten var . Değiştirme /proc/sys/vm/overcommit_memory, düşük bellekteki çekirdek davranışını etkiler.
jofel

1
Evet, ancak overcommit_memoryözel dosya kullanılabilir bellek olarak RAM + SWAP kullanır. Hala takas edeceğim :)

1
Bunun nasıl bir kopyası olmadığını da açıklamanız gerekir: Unix.stackexchange.com/questions/34334/… , WRT gruplarıyla ve bireysel kullanıcılarla çelişiyor. PS. Değiştirmek istemiyorsanız, değiştirmeyi devre dışı bırakın .
goldilocks

1
Takas istiyorum! Hazırda bekletme modunu istiyorum, kullanılmayan baytların depolanmasını istiyorum ! Ama kullanılmış baytların orada saklanmasını istemiyorum . Bağlantı hakkında, ulimitsneredeyse her yerde gösterildiği gibi kötü bir fikir çünkü işlem başına bir sınırlama ... Biliyorum çatal :) Hakkında cgroups, bu kesinlikle daha iyi ama daha genel bir şey yok: Dizüstü bilgisayarım hakkında konuşuyorum ama ben de paylaşacağımız üç tane "hesaplama" sunucusuna sahip olmak Kullanıcı sınırlarına göre bu tür bir zorlama yaparsam, en kötü senaryo ile sınırlı olacağım, değil mi?

1
cgroups, bir kullanıcının tüm süreçlerini ayrı bir gruba kararlaştırdığınız sürece uygulanır ve istediğinizi yapmalıdır.
peterph

Yanıtlar:


4

Birisi duyduğunda önerdi cgroups. Size bu yönü sağlamaya çalışın:

  • seçtiğiniz bir grup göreve uygulanır (dolayısıyla sistem çapında değil, her işlem için de değil)
  • grup için limitler belirlenir
  • limitler statik
  • bellekte ve / veya bellekte + takasta sabit sınır uygulayabilirler

Böyle bir şey sizi hedeflerinize yaklaştırabilir :

group limited {
  memory {
    memory.limit_in_bytes = 50M;
    memory.memsw.limit_in_bytes = 50M;
  }
}

Bu, bu grup altındaki görevlerin yalnızca maksimum 50M bellekte ve 50M bellek + takasta kullanılabileceğini söyler, bu nedenle bellek dolduğunda takas olmaz, ancak bellek dolu değilse ve bazı veriler eşleştirilebiliyorsa takas, buna izin verilebilir.

İşte grubun hafıza belgelerinden bir alıntı :

Memsw limitini kullanarak, takas sıkıntısından kaynaklanabilecek OOM sisteminden kaçınabilirsiniz.


Hala tam olarak ne bekliyordum. Ama beklediğim ve gerçeklik arasındaki fark genellikle oldukça büyük :) Bu durumda, overcommit_memoryçekirdek değişkeni gibi bir şey kaçırmadım emin olmak istedim . Hepinize teşekkür ederim.

0

Sık sık aynı problemle karşılaşıyorum. Genel iş akışım MATLAB'da yoğun hesaplama gerektiriyor. Bazen istemeden kullanılabilir bellek miktarını aşan yeni bir değişken tahsis etmeye çalışacağım. Sistem kilitleniyor ve işe geri dönmek için makineyi genellikle yeniden başlatmam gerekiyor. : P

Benim durumumda ve sizinki gibi geliyor, MATLAB'ın kullandığı bellek miktarını statik bir miktarla sınırlamakla çok ilgili değildim - Donmuş bir makineye sahip olmak istemiyordum ve MATLAB sürecimi feda etmeye istekliydim Sistem yanıt verebilirliğini korumak için.

Bu yazının bir yanıtından esinlenerek , aşağıdaki komut dosyasını yazdım (watch_memory.sh olarak adlandırdım):

#!/bin/bash

MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')

MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))

while :; do
    if [ "$MEM_PERC" -gt "95" ]
    then
        kill $1
        echo "$1 killed for using too much memory."
        exit
    fi
    sleep 1

    MONITOR=$(free | grep 'buffers/cache:')
    MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
    MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
    MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
done

Bu komut dosyası saniyede bir boş bellek miktarını kontrol eder. Sistem bittiğinde, "günah keçisi" pidiniz (senaryoya argüman olarak aktarılır) öldürülür.

Senaryonun önceliğini (güzelliğini) ayarlamadan günah keçisinin öldürülmesi yaklaşık 10-20 saniye sürdü, ama yine de çalıştı. Betiğin negatif önceliğe sahip olarak çalıştırılması, ihlalden sonra anında öldürmeyle sonuçlandı (bu örnekte 11916, bellek tükendiğinde öldürmek istediğim pid):

sudo nice -n -5 bash watch_memory.sh 11916
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.