2013-04-16 23 views
6

ja wykonujące bardzo szybki dostęp do plików w Ruby (2.0.0 p39474), i wciąż otrzymuję wyjątek Too many open filesRuby zarządzanie uchwyt pliku (zbyt wiele otwartych plików)

Spojrzeliśmy na this thread, here i różne inne źródła , Dobrze znam ograniczenia systemu operacyjnego (ustawione na 1024 w moim systemie).

Część mojego kodu, który wykonuje ten plik dostępu mutexed i przybiera postać:

File.open(filename, 'w'){|f| Marshal.dump(value, f) } 

gdzie filename podlega szybkim zmianom, w zależności od wywołującego wątku sekcję. Rozumiem, że ta forma rezygnuje z obsługi pliku po bloku.

Mogę zweryfikować liczbę obiektów File, które są otwarte przy użyciu ObjectSpace.each_object(File). Oznacza to, że w pamięci jest maksymalnie 100 rezydentów, ale tylko jeden jest otwarty, zgodnie z oczekiwaniami.

Ponadto, sam wyjątek jest zgłaszany w czasie, gdy obiekty o numerach 10-40 File są zgłaszane przez ObjectSpace. Ponadto, ręczne zbieranie nieużytków nie poprawi żadnego z tych obliczeń, podobnie jak spowolnienie mojego skryptu poprzez wstawienie wywołań sleep.

Moje pytanie brzmi zatem:

  • Am I zasadniczo niezrozumienia charakteru granicy OS --- nie obejmuje cały okres procesu?
    • Jeśli tak, to w jaki sposób serwery internetowe unikają awarii po uzyskaniu dostępu do plików ponad ulimit -n?
    • Czy ruby ​​zachowuje swoje uchwyty plików poza systemem obiektowym, czy też jądro po prostu bardzo wolno liczy się z "współbieżnym" dostępem?

Edit 20130417: strace wskazuje, że Ruby nie zapisuje wszystkie dane do pliku, wracając i zwalniając mutex przed tym zakresie. W związku z tym plik obsługuje stos aż do limitu systemu operacyjnego.

Próbując naprawić to, użyłem syswrite/sysread, tryb synchroniczny, a nazywa flush przed close. Żadna z tych metod nie zadziałała.

Moje pytanie zostało zmienione na: Dlaczego ruby ​​nie może zamknąć swoich uchwytów plików i jak mogę to zmusić?

Odpowiedz

3

Zastosowanie dtrace lub strace lub cokolwiek równoważne jest w systemie, i dowiedzieć się dokładnie, jakie pliki są otwarte.

Należy pamiętać, że mogą to być gniazda.

Zgadzam się, że wklejony kod wydaje się nie być w stanie spowodować tego problemu, przynajmniej nie bez dość dziwnego błędu współbieżności.

+0

'strace' wskazuje, że rubin otwiera plik, a następnie wraca z funkcji, zwalniając muteks przed zapisaniem danych. W niektórych przypadkach nawet się nie wypala i kończy na zapisie na dysku podczas zamykania zasobów po wystąpieniu wyjątku (np. Podczas zamykania). –