2013-04-16 14 views
6

Ich bin sehr schnellen Zugriff auf Dateien in Ruby (2.0.0 p39474) durchgeführt wird, und halten Sie die Ausnahme bekommen Too many open filesRuby-Datei-Handle-Management (zu viele offene Dateien)

bei this thread schaute haben, here und verschiedene andere Quellen Ich bin mir der Grenzen des Betriebssystems bewusst (auf meinem System auf 1024 gesetzt).

Der Teil meines Code, der diesen Dateizugriff durchführt, wird mutexed, und nimmt die Form:

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

wo filename einem schnellen Wandel unterworfen ist, abhängig von dem Thread des Abschnitt aufrufen. Es ist mein Verständnis, dass diese Form nach dem Block ihr Datei-Handle abgibt.

Ich kann die Anzahl der File Objekte überprüfen, die unter Verwendung von ObjectSpace.each_object(File) geöffnet sind. Dies meldet, dass bis zu 100 Bewohner im Speicher sind, aber nur einer ist wie erwartet geöffnet.

Weiter wird die Ausnahme selbst ausgelöst, wenn nur 10 bis 40 File Objekte von ObjectSpace gemeldet werden. Darüber hinaus verbessert die manuelle Speicherbereinigung diese Anzahl nicht, ebenso wie das Verlangsamen des Skripts durch das Einfügen von sleep Aufrufen. deshalb

Meine Frage ist,:

  • Bin ich die Art der OS Grenze grundsätzlich Mißverständnis --- macht es die ganze Lebensdauer eines Prozesses abdecken?
    • Wenn ja, wie Web-Server zu vermeiden Absturz über ulimit -n Dateien nach dem Zugriff aus?
    • Behält Ruby seine Datei-Handles außerhalb seines Objektsystems bei oder ist der Kernel nur sehr langsam beim Zählen von "gleichzeitigem" Zugriff?

bearbeiten 20.130.417: strace zeigt an, dass Rubin, bevor Sie so nicht in die Datei alle seine Daten schreiben, Rückkehr und den Mutex freizugeben. Daher werden die Dateihandles bis zum Betriebssystemlimit gestapelt.

In einem Versuch, dieses Problem zu beheben, ich habe syswrite/sysread, Synchronmodus verwendet, und flush vor close genannt. Keine dieser Methoden hat funktioniert.

Meine Frage wird so revidiert zu: Warum kann Ruby seine Dateigriffe nicht schließen, und wie kann ich es dazu zwingen?

Antwort

3

Verwenden dtrace oder Strace oder was auch immer gleichwertig ist auf Ihrem System, und finden Sie genau heraus, welche Dateien geöffnet werden.

Beachten Sie, dass dies Sockets sein können.

Ich stimme zu, dass der Code, den Sie eingefügt haben, nicht in der Lage ist, dieses Problem zu verursachen, zumindest nicht ohne einen ziemlich seltsamen Nebenläufigkeitsfehler.

+0

"strace" zeigt an, dass Ruby die Datei öffnet und dann von der Funktion zurückkehrt, wobei der Mutex freigegeben wird, bevor die Daten geschrieben werden. In einigen Fällen wird es nicht einmal gespült und endet beim Schreiben von Ressourcen nach der Ausnahme (d. H. Während des Herunterfahrens) beim Schreiben auf die Festplatte. –

Verwandte Themen