Gibt die Konsole eine blockierende Operation aus?

8

Wenn ein Java-Programm System.out.println () oder ein Scala-Programm aufruft, ruft println () den Threadblock auf?

Ich schreibe ein Scala-Programm mit einer großen Anzahl von Teilaufgaben. Jede Teilaufgabe wird innerhalb einer Zukunft ausgeführt. Es wird empfohlen, den Code innerhalb von Akteuren und Futures nicht zu blockieren, damit auch nachfolgende Aufgaben nicht warten müssen. Aber ich möchte sehr viel auf der Konsole drucken.

Und wenn es eine blockierende Operation ist: Was kann ich tun, um die Leistung zu optimieren?

  • Soll ich einen dedizierten Thread für die Konsolenausgabe verwenden, so dass nur der Thread blockiert?
  • Irgendwelche anderen Ratschläge?

Natürlich könnte ich versuchen, die Menge der Ausgabe zu reduzieren oder einige Ausgaben in einem StringBuilder zu sammeln und sie zusammen in einem Stapel zu drucken, was die Anzahl der Ausgabeoperationen reduziert.

    
user573215 25.06.2013, 17:41
quelle

2 Antworten

12
  

Wenn ein Java-Programm System.out.println () oder ein Scala-Programm aufruft, ruft println () den Threadblock auf?

Ja und nein. System.out ist eine PrintStream , die eine synchronisierte Klasse ist. Mehrere Threads, die große Mengen in System.out schreiben, blockieren sich also gegenseitig. Sobald ein Thread die Sperre erhält, hängt es jedoch von der Architektur ab, ob der IO den Thread blockiert. Wenn Sie eine große Menge an IO schreiben, die die Kapazität der zugrunde liegenden Hardware überwältigt, wird der -Schreibvorgang blockiert. Auch eine Menge kleiner Schreibvorgänge (im Gegensatz zu gepuffert) verlangsamt den Thread ebenfalls.

  

Sollte ich einen dedizierten Thread für die Konsolenausgabe verwenden, so dass der Thread der einzige ist, der blockiert?

Ausgezeichnete Idee, ja. Dann könnte dieser Thread durch ein einzelnes BufferedWriter oder eine Art log4j oder ein anderes Protokollierungspaket schreiben, das im Vergleich zu System.out viel performanter wäre. Sie müssen etwas wie BlockingQueue verwenden, um die Nachrichten in eine Warteschlange zu stellen, die synchron ist, aber die E / A wird diese Warteschlange niemals blockieren, es sei denn, Sie produzieren Nachrichten schneller als der E / A-Kanal kann sie beibehalten.

  

Natürlich könnte ich versuchen, die Menge der Ausgabe zu reduzieren oder einige Ausgaben in einem StringBuilder zu sammeln und sie zusammen in einem Stapel zu drucken, was die Anzahl der Ausgabeoperationen reduziert.

Das BufferedWriter wird sich darum kümmern.

  

Irgendwelche anderen Ratschläge?

  • Wie bereits erwähnt, verwenden Sie ein besseres Protokollierungspaket oder einen Singlethread-Writer.
  • Schreiben Sie Protokolle auf eine andere physische Festplatte mit mehr E / A-Bandbreite.
  • Wechseln Sie zu einem Speicherdateisystem oder einer Hardware, um die E / A-Bandbreite zu erhöhen. SSD ++.
  • Senden Sie es über das Netzwerk an eine andere Box, um die tatsächlich ausbleibende Box zu machen.
  • Verwenden Sie GzipOutputStream , um es im laufenden Betrieb zu komprimieren.
Gray 25.06.2013, 17:46
quelle
4

Es kommt darauf an . Auf Windows OS ist es eine blockierende Operation und beinhaltet eine Menge Kernel-Kram, um etwas auf die Konsole zu drucken. In UNIX -ähnlichen Betriebssystemen wird die Operation gepuffert, so dass sie nicht als langsam empfunden wird.

Ich würde vorschlagen, dass Sie mit Ihrem Pufferansatz gehen und einen separaten Thread haben, ist auch eine gute Idee. Oder wenn Ihre Ausgabe nicht so wichtig ist, könnten Sie sie in eine Datei schreiben, was viel schneller ist als das Schreiben in die Konsole.

    
darijan 25.06.2013 17:45
quelle