2012-03-26 21 views
6

To jest najdziwniejsze!System operacyjny zaczyna zabijać procesy, gdy działa wielowątkowy proces python

Mam wielowątkową aplikację kliencką napisaną w języku Python. Używam wątkowania do jednoczesnego pobierania i przetwarzania stron. Chciałbym użyć multi-handle cURL, z tym że wąskim gardłem jest zdecydowanie procesor (nie przepustowość) w tej aplikacji, więc bardziej efektywne jest użycie puli wątków.

Mam 64b i7 kołyszący 16 GB RAM. Silny. Uruchomienie 80 wątków podczas słuchania Pandory i trollingu Stackoverflow i BAM! Proces rodzic czasami kończy się komunikatem

Killed

Inne czasy jednej stronie (co jest jego własny proces w Chrome) umrze. Innym razem zawiesza się cała przeglądarka.

Jeśli chcesz zobaczyć trochę kod tutaj jest sedno to:

Oto proces nadrzędny:

def start(): 
    while True: 
    for url in to_download: 
     queue.put((url, uri_id)) 

    to_download = [ ] 

    if queue.qsize() < BATCH_SIZE: 
     to_download = get_more_urls(BATCH_SIZE) 

    if threading.activeCount() < NUM_THREADS: 
     for thread in threads: 
     if not thread.isAlive(): 
      print "Respawning..." 
      thread.join() 
      threads.remove(thread) 
      t = ClientThread(queue) 
      t.start() 
      threads.append(t) 

    time.sleep(0.5) 

I tu jest sedno ClientThread:

class ClientThread(threading.Thread): 

    def __init__(self, queue): 
    threading.Thread.__init__(self) 
    self.queue = queue 

    def run(self): 
    while True: 
     try: 
     self.url, self.url_id = self.queue.get() 
     except: 
     raise SystemExit 

     html = StringIO.StringIO() 
     curl = pycurl.Curl() 
     curl.setopt(pycurl.URL, self.url) 
     curl.setopt(pycurl.NOSIGNAL, True) 
     curl.setopt(pycurl.WRITEFUNCTION, html.write) 
     curl.close() 

     try: 
     curl.perform() 
     except pycurl.error, error: 
     errno, errstr = error 
     print errstr 

     curl.close() 

EDYCJA: Och, racja ... zapomniałem zadać pytanie ... powinno być oczywiste: Dlaczego moje procesy zostają zabite? Czy dzieje się to na poziomie OS? Poziom jądra? Czy jest to spowodowane ograniczeniem liczby otwartych połączeń TCP, jakie mogę mieć? Czy jest to ograniczenie liczby wątków, które mogę uruchomić jednocześnie? Wyjście cat /proc/sys/kernel/threads-max to 257841. Więc ... Nie sądzę, żeby to było ...

Myślę, że mam to ... OK ... Nie mam żadnej przestrzeni wymiany na moim dysku. Czy istnieje sposób na utworzenie przestrzeni wymiany? Używam Fedory 16. Byłem zamieniony ... następnie włączyłem całą moją pamięć RAM i zniknęło to magicznie. Ogonków /var/log/messages znalazłem ten błąd.

Mar 26 19:54:03 gazelle kernel: [700140.851877] [15961] 500 15961 12455  7292 1  0    0 postgres 
Mar 26 19:54:03 gazelle kernel: [700140.851880] Out of memory: Kill process 15258 (chrome) score 5 or sacrifice child 
Mar 26 19:54:03 gazelle kernel: [700140.851883] Killed process 15258 (chrome) total-vm:214744kB, anon-rss:70660kB, file-rss:18956kB 
Mar 26 19:54:05 gazelle dbus: [system] Activating service name='org.fedoraproject.Setroubleshootd' (using servicehelper) 
+1

Sprawdź wyjście 'dmesg (8)', aby zobaczyć jeśli jądro zalogowało się jakiekolwiek informacje. – sarnold

+0

Dzięki ... zrobi ... – KeatsKelleher

+0

ostatnie wpisy w 'dmesg (8)' odnoszą się do mojego adaptera Wi-Fi z moim routerem. ... które było kilka godzin temu – KeatsKelleher

Odpowiedz

7

pan wyzwalane przez jądro Sterownik braku pamięci (OOM); wybiera, które procesy zabijać w skomplikowany sposób, aby trudne było zabicie jak najmniejszej liczby procesów, aby wywrzeć największy wpływ. Wygląda na to, że Chrome najbardziej zachęcający proces zabija zgodnie z kryteriami, z których korzysta jądro.

można zobaczyć podsumowanie kryteriów w proc(5) podręcznika pod pliku /proc/[pid]/oom_score:

/proc/[pid]/oom_score (since Linux 2.6.11) 
      This file displays the current score that the kernel 
      gives to this process for the purpose of selecting a 
      process for the OOM-killer. A higher score means that 
      the process is more likely to be selected by the OOM- 
      killer. The basis for this score is the amount of 
      memory used by the process, with increases (+) or 
      decreases (-) for factors including: 

      * whether the process creates a lot of children using 
      fork(2) (+); 

      * whether the process has been running a long time, or 
      has used a lot of CPU time (-); 

      * whether the process has a low nice value (i.e., > 0) 
      (+); 

      * whether the process is privileged (-); and 

      * whether the process is making direct hardware access 
      (-). 

      The oom_score also reflects the bit-shift adjustment 
      specified by the oom_adj setting for the process. 

Można dostosować plik oom_score dla programu Pythona, jeśli ma to być jeden, który zostanie zabity.

Prawdopodobnie lepszym rozwiązaniem jest dodanie więcej swapu do systemu, aby spróbować przesunąć czas, w którym wywoływany jest OOM-killer. Oczywiście, posiadanie większej wymiany niekoniecznie oznacza, że ​​Twój system nigdy nie zabraknie pamięci - i możesz nie zadbać o sposób, w jaki radzi sobie, jeśli jest dużo ruchu typu "swap" - ale może przynajmniej sprawić, że będziesz się starał problemy z pamięcią.

Jeśli już zostało przydzielone całe miejsce dostępne dla partycji wymiany, można dodać pliki wymiany pliki. Ponieważ przechodzą przez system plików, jest więcej narzutów na pliki wymiany niż na partycje wymiany, ale można je dodać po podzieleniu dysku na partycje, co sprawia, że ​​jest to łatwe rozwiązanie krótkoterminowe. Użyj polecenia dd(1), aby przydzielić plik (, nie używaj seek, aby utworzyć plik rozrzedzony), a następnie użyj formatu mkswap(8), aby sformatować plik do użycia w zamian, a następnie użyj swapon(8), aby włączyć ten konkretny plik. (Myślę, że możesz nawet dodać pliki wymiany do fstab(5), aby były automatycznie dostępne przy następnym ponownym uruchomieniu komputera, ale nigdy nie próbowałem i nie znam składni.)

+0

Dzięki, człowieku :) To jest to! – KeatsKelleher

0

Robisz

raise SystemExit 

które faktycznie opuszczającego interpreter Pythona i nie wątku używasz w

+0

To dobrze, nie wyjaśnia, dlaczego zupełnie odrębny proces umiera. Zobacz edycję powyżej. – KeatsKelleher