endl, flush, /n



  • Ein/Ausgabe wird letztendlich vom Betriebssystem erledigt. Ein Programm erteilt dem Betriebssystem den Befehl, etwas auszugeben (sei es auf den Bildschirm, in eine Datei, in eine Netzverbindung (Socket), etc.) über einen sogenannten Systemaufruf (Syscall). Das Problem: Systemaufrufe sind langsam. Also sollte man nicht jedes Zeichen einzeln ausgeben, sondern möglichst erst ein paar Zeichen ansammeln, bevor man alle zusammen ausgibt.

    Das ist die Idee der gepufferten Ein/Ausgabe: Alles geht erstmal in einen Puffer, und spätestens wenn der Puffer voll ist, wird er geflusht, dh insgesamt über einen einzelnen Systemaufruf an das Betriebssystem übergeben. Manchmal möchte man schon vorher flushen, warum auch immer (z.B. für Debugausgaben, die noch erscheinen sollen, bevor das Programm abschmiert), dann kann man das mit flush oder endl tun.

    Ich hoffe, das genügt erstmal zum Verständnis.


  • Mod

    flushi schrieb:

    Ausgabe kostet eh viel Zeit, deswegen ist es in den meisten Fällen egal, ob man endl oder \n nimmt, obwohl bei letzterem die Performance geringfügig besser ist. endl ist dann wichtig, wenn eine Ausgabe sofort erfolgen soll, z.B. als hinweis vor einer längeren Rechnung ("bitte warten ...")

    Ich fordere dich hiermit auf, deine Ausgabe mal in eine Datei umzuleiten. Viel Spass mit zigmal langsameren Schreiben. Ausserdem ruft dich hinterher der Admin an, welcher Spinner 25.000 Schreibvorgaenge pro Sekunde auf die Platte macht.



  • SeppJ schrieb:

    Ausserdem ruft dich hinterher der Admin an, welcher Spinner 25.000 Schreibvorgaenge pro Sekunde auf die Platte macht.

    flush != auf Platte schreiben!
    Da ist noch mindestens der Buffer des Betriebssystems dazwischen.

    Langsam ist es nur aufgrund der Syscalls.


  • Mod

    lolJ schrieb:

    flush != auf Platte schreiben!
    Da ist noch mindestens der Buffer des Betriebssystems dazwischen.

    Na, dann probier mal aus, was bei einem flush der Buffer des Betriebssystems bei den allermeisten Implementierungen macht. Falls du eine findest, die bei einem flush nicht auf die Platte schreibt, dann bitte melden, das moechte ich dann naemlich ausprobieren.



  • Ein flush ist (unter unixoiden) ein write-Syscall. Du willst also sagen, dass jedes write die Festplatte ackern lässt?


  • Mod

    Bashar schrieb:

    Ein flush ist (unter unixoiden) ein write-Syscall. Du willst also sagen, dass jedes write die Festplatte ackern lässt?

    Es aktualisiert mindestens das Dateisystem. Ob die Daten physisch auf der Platte landen, ist schwer zu pruefen. Aber der Admin ruft dich wegen den 25.000 Calls an den Fileserver an. Die gehen naemlich wirklich raus.



  • lolJ schrieb:

    SeppJ schrieb:

    Ausserdem ruft dich hinterher der Admin an, welcher Spinner 25.000 Schreibvorgaenge pro Sekunde auf die Platte macht.

    flush != auf Platte schreiben!
    Da ist noch mindestens der Buffer des Betriebssystems dazwischen.

    Dann wäre flush komplett nutzlos. Wenn flush zurückkehrt ist garantiert, dass wenn du den Stecker ziehst, dass du die Daten nach einem Neustart lesen kannst. Es muss dafür nicht unbedingt auf die Festplatte, aber mindestens in einen persistenten Speicher (Flash oder so). Ich weiß es gibt Dateisystemmodi und Festplatten, die das falsch machen, das ändert aber nichts an der Bedeutung. Es ist unbedingt notwendig ein korrektes flush zu haben um Transaktionen zu implementieren, also entweder Datei wurde geschrieben oder nicht, aber keine kaputten Daten.
    Ich habe mal eine Anekdote gehört, dass Windows 95 (Versionen vergessen, ist auch egal) einen Bug hatte, dass flush ein noop war. Programmierer haben per Benchmark gemerkt, dass flush echt schnell ist und haben es in ihren Programmen reichlich benutzt, weil es sicherer ist und praktisch nichts kostet. Dann hat Win98 den Bug gefixt und die Programme liefen grotten langsam, weil sie tatsächlich nen flush ausgeführt haben. Microsoft hat daraufhin den sicheren und den schnellen Modus in die Einstellungen getan, der eine hat den Bug und der andere nicht.

    Bashar schrieb:

    Ein flush ist (unter unixoiden) ein write-Syscall. Du willst also sagen, dass jedes write die Festplatte ackern lässt?

    Ja. Mindestens einen kleinen Flash-Chip. Obwohl natürlich cout nicht die Festplatte, sondern den Bildschirm ackern lässt.

    lolJ schrieb:

    Langsam ist es nur aufgrund der Syscalls.

    Wie lange dauert ein Syscall? Hier steht ~20 Microsekunden. Das ist nichts im Vergleich zu einem Festplattenzugriff. Damit ist der Syscalloverhead komplett irrelevant.



  • SeppJ schrieb:

    Bashar schrieb:

    Ein flush ist (unter unixoiden) ein write-Syscall. Du willst also sagen, dass jedes write die Festplatte ackern lässt?

    Es aktualisiert mindestens das Dateisystem. Ob die Daten physisch auf der Platte landen, ist schwer zu pruefen.

    Gehen wir mal von Nein aus, das wäre nämlich äußerst dämlich andernfalls.

    Aber der Admin ruft dich wegen den 25.000 Calls an den Fileserver an. Die gehen naemlich wirklich raus.

    Vielleicht ist das bei deiner Computerphysik so, weiß ich nicht. Ich hab nie erlebt, dass deswegen ein Admin angerufen hat. Wahrscheinlich hat das überhaupt keiner gemerkt. Außer mir und dem armen Programm, was dann abgeschossen werden musste, natürlich.


  • Mod

    Dein lokales Programm wird natuerlich auch aeusserst langsam, wenn man nach jeder Zeile flusht, denn das flush ist nicht nur teuer wegen dem Kontextwechsel, sondern auch weil der Syscall richtig viel Arbeit im Rechner ausloest. Von

    flushi schrieb:

    geringfügig besser

    kann jedenfalls gar keine Rede sein, ausser bei Bildschirmausgaben (wo '\n' == endl).



  • nwp3 schrieb:

    lolJ schrieb:

    SeppJ schrieb:

    Ausserdem ruft dich hinterher der Admin an, welcher Spinner 25.000 Schreibvorgaenge pro Sekunde auf die Platte macht.

    flush != auf Platte schreiben!
    Da ist noch mindestens der Buffer des Betriebssystems dazwischen.

    Dann wäre flush komplett nutzlos. Wenn flush zurückkehrt ist garantiert, dass wenn du den Stecker ziehst, dass du die Daten nach einem Neustart lesen kannst.

    Nein.

    Es muss dafür nicht unbedingt auf die Festplatte, aber mindestens in einen persistenten Speicher (Flash oder so). Ich weiß es gibt Dateisystemmodi und Festplatten, die das falsch machen, das ändert aber nichts an der Bedeutung. Es ist unbedingt notwendig ein korrektes flush zu haben um Transaktionen zu implementieren, also entweder Datei wurde geschrieben oder nicht, aber keine kaputten Daten.

    Das machst du aber nicht mit einem stinknormalen flush aus der iostreams-Library.

    Bashar schrieb:

    Ein flush ist (unter unixoiden) ein write-Syscall. Du willst also sagen, dass jedes write die Festplatte ackern lässt?

    Ja. Mindestens einen kleinen Flash-Chip.

    Seit wann gibts das, seit 5 Jahren? Ich weiß nicht, ob meine Platte sowas hat. Und ich würde im Normalfall nicht davon ausgehen. Außerdem bin ich selbst wenn sowas vorliegt skeptisch, ob das OS die Daten beim write direkt in den Flash schreibt.

    Obwohl natürlich cout nicht die Festplatte, sondern den Bildschirm ackern lässt.

    Ein-/Ausgabeumleitung :p



  • Bashar schrieb:

    nwp3 schrieb:

    lolJ schrieb:

    SeppJ schrieb:

    Ausserdem ruft dich hinterher der Admin an, welcher Spinner 25.000 Schreibvorgaenge pro Sekunde auf die Platte macht.

    flush != auf Platte schreiben!
    Da ist noch mindestens der Buffer des Betriebssystems dazwischen.

    Dann wäre flush komplett nutzlos. Wenn flush zurückkehrt ist garantiert, dass wenn du den Stecker ziehst, dass du die Daten nach einem Neustart lesen kannst.

    Nein.

    Wie nein? Doch! Was tut denn flush deiner Meinung nach? Sinnlos Zeit verschwenden?

    Bashar schrieb:

    nwp3 schrieb:

    Es muss dafür nicht unbedingt auf die Festplatte, aber mindestens in einen persistenten Speicher (Flash oder so). Ich weiß es gibt Dateisystemmodi und Festplatten, die das falsch machen, das ändert aber nichts an der Bedeutung. Es ist unbedingt notwendig ein korrektes flush zu haben um Transaktionen zu implementieren, also entweder Datei wurde geschrieben oder nicht, aber keine kaputten Daten.

    Das machst du aber nicht mit einem stinknormalen flush aus der iostreams-Library.

    Ein bisschen mehr Arbeit ist es schon. Erst die neue Version schreiben, flush, flag auf Platte schreiben, flush, alte Version mit neuer Version überschreiben, flush, flag entfernen, flush, Nutzer sagen dass jetzt alles sicher ist. Das flush braucht man deshalb, weil jederzeit jemand den Stecker ziehen kann. Und wenn das passiert, musst du entweder die alte oder die neue Version recovern können. Und das flush aus der Standardbibliothek ist genau für sowas da. Deswegen finde ich es auch nervig wenn Leute aus Unwissenheit endl schreiben.

    Bashar schrieb:

    nwp3 schrieb:

    Bashar schrieb:

    Ein flush ist (unter unixoiden) ein write-Syscall. Du willst also sagen, dass jedes write die Festplatte ackern lässt?

    Ja. Mindestens einen kleinen Flash-Chip.

    Seit wann gibts das, seit 5 Jahren? Ich weiß nicht, ob meine Platte sowas hat. Und ich würde im Normalfall nicht davon ausgehen. Außerdem bin ich selbst wenn sowas vorliegt skeptisch, ob das OS die Daten beim write direkt in den Flash schreibt.

    Wenn deine Festplatte keinen kleinen Flash-Chip hat muss es die Daten halt auf die Magnetscheibe schreiben und das kann auch mal 200ms dauern. Das Kriterium ist persistente Speicherung, Flash oder Magnetscheibe ist egal. Aber in der Praxis hast du natürlich recht mit deinen Zweifeln. Die meisten Dateisysteme und Festplatten sind so eingestellt, dass flush nicht flusht, weil das zu langsam wäre. Die Geschwindigkeit erkauft man sich damit, dass man mit etwas Pech beim Stecker ziehen sein Dateisystem komplett zerschrotet. Aber sowas sollte man ja auch nicht tun.
    ZFS ist in dieser Beziehung genial, weil es Transaktionen kann und das auch noch schnell und man jederzeit den Stecker ziehen kann und es dadurch nicht kaputt gehen kann.



  • fflush(3)

    NOTES
           Note that fflush() only flushes the user-space buffers provided by the C  library.
           To  ensure  that  the data is physically stored on disk the kernel buffers must be
           flushed too, for example, with sync(2) or fsync(2).
    

    Wenn man damit rechnet, dass jemand den Stecker rausziehen kann, dann kann das auch während dem fsync passieren. (Alle gängigen FS unter Linux sind übrigens immer in einem konsistenten Zustand, selbst wenn man den Strom abstellt.)



  • nwp3 schrieb:

    Bashar schrieb:

    nwp3 schrieb:

    lolJ schrieb:

    SeppJ schrieb:

    Ausserdem ruft dich hinterher der Admin an, welcher Spinner 25.000 Schreibvorgaenge pro Sekunde auf die Platte macht.

    flush != auf Platte schreiben!
    Da ist noch mindestens der Buffer des Betriebssystems dazwischen.

    Dann wäre flush komplett nutzlos. Wenn flush zurückkehrt ist garantiert, dass wenn du den Stecker ziehst, dass du die Daten nach einem Neustart lesen kannst.

    Nein.

    Wie nein? Doch! Was tut denn flush deiner Meinung nach? Sinnlos Zeit verschwenden?

    Hab ich bereits geschrieben, aber für dich tu ichs gerne nochmal. flush übergibt die Daten aus dem Streambuffer an das Betriebssystem, typischerweise über einen Aufruf wie write.

    Das ist alles. Siehe auch das Posting von "tatsache" über mir.



  • Bashar schrieb:

    flush übergibt die Daten aus dem Streambuffer an das Betriebssystem, typischerweise über einen Aufruf wie write.

    Das ist alles. Siehe auch das Posting von "tatsache" über mir.

    Was soll das bewirken? Ich glaube schon dass es bei bestimmten Implementationen so ist, aber das ist ein Bug, kein Feature. Genauso hätte ich behauptet, dass std::string kein copy on write hat. Hat es aber im gcc. Wir müssen hier wohl zwischen "Was tut flush" und "Was tut eine bestimmte Implementation von flush" unterscheiden. Und nur weil in irgendwelchen Notes ein Bug dokumentiert ist sehe ich das nicht als ein Beleg dafür an, was flush tut.


  • Mod

    nwp3 schrieb:

    Bashar schrieb:

    flush übergibt die Daten aus dem Streambuffer an das Betriebssystem, typischerweise über einen Aufruf wie write.

    Das ist alles. Siehe auch das Posting von "tatsache" über mir.

    Was soll das bewirken?

    Ab dann wirkt es fuer den Rest des Systems so, als waeren die Daten geschrieben, da das Dateisystem aktualisiert wurde (eine sehr teure Aktion!). Das heisst, ab dann wird der Inhalt der Datei mit den neuen Daten angezeigt, wenn man ihn sich von anderswo her ausgeben laesst. Ob das Dateisystem tatsaechlich die Daten physisch schreibt ist aber ohne Werkzeuge auf Kernelebene wohl so gut wie unmoeglich fest zu stellen. Soweit ich weiss hat Bashar hier recht und es wird in der Regel nicht physisch geschrieben, ausser man* macht einen sync-Syscall.

    *: Das kann und wird auch von Zeit zu Zeit von anderer Stelle ausgeloest werden. Linux hat mWn einen Daemon laufen (Stichowrt: pdflush), der in bestimmten Abstaenden (und nach ein paar anderen Kriterien) synct.



  • nwp3 schrieb:

    Bashar schrieb:

    flush übergibt die Daten aus dem Streambuffer an das Betriebssystem, typischerweise über einen Aufruf wie write.

    Das ist alles. Siehe auch das Posting von "tatsache" über mir.

    Was soll das bewirken? Ich glaube schon dass es bei bestimmten Implementationen so ist, aber das ist ein Bug, kein Feature.

    Die grundsätzliche Richtung stimmt schon, man flusht, weil man die Daten früher auf der Platte haben will. Aber es gibt halt normalerweise keine Garantie, weil immer noch das OS und die Hardware dazwischenfunken können. Mehr als das ist halt auch nicht spezifiziert, oder kennst du eine Spezifikation, die das so fordert? BTW du behauptest die ganze Zeit das sei ein Bug ... in welcher Implementation von flush passiert denn mehr als das?

    Genauso hätte ich behauptet, dass std::string kein copy on write hat. Hat es aber im gcc.

    Das ist ja eine Frage der internen Implementation. flush interagiert aber mit dem Betriebssystem, und das was du als Verhalten von flush verkaufen willst ist in Wirklichkeit das Verhalten des Betriebssystems nach dem write. (BTW auch der Grund, warum ich dir die Geschichte mit dem Windows95-Bug nicht ganz abnehme. Wäre gut, wenn du das nochmal irgendwo finden könntest. Vielleicht ist es ein Bug in der msvc-Runtime gewesen?)

    Und nur weil in irgendwelchen Notes ein Bug dokumentiert ist sehe ich das nicht als ein Beleg dafür an, was flush tut.

    Die Bugs sind in einer Sektion mit der Überschrift "BUGS" beschrieben (so vorhanden, was bei fflush nicht anzunehmen ist.)



  • Bashar schrieb:

    (BTW auch der Grund, warum ich dir die Geschichte mit dem Windows95-Bug nicht ganz abnehme. Wäre gut, wenn du das nochmal irgendwo finden könntest. Vielleicht ist es ein Bug in der msvc-Runtime gewesen?)

    Hier steht was dazu. War wohl Win 3.11 mit dem Bug.

    Bashar schrieb:

    Genauso hätte ich behauptet, dass std::string kein copy on write hat. Hat es aber im gcc.

    Das ist ja eine Frage der internen Implementation.

    Ich wollte darauf hinaus, dass der C++-Standard Copy On Write bei std::string inzwischen verbietet. Deswegen würde ich sagen, dass string kein Copy On Write kann. Und der gcc kann es doch. Meiner Meinung nach legt die Dokumentation/Standard fest was eine Funktion tut, nicht eine Implementation, daher ist in meinem Weltbild die Aussage "string kann kein Copy On Write" trotz widersprechendem gcc korrekt. Gleichsam mit flush. Nur weil es in Linux so ist heißt nicht dass es so ist. Aber ich habe mich wohl geirrt. flush = Cache updaten erscheint durchaus sinnvoll. Ich sollte irgendwie besser markieren/auseinander halten was bei mir Wissen, Vorstellung und Halbwissen ist. 😞


Anmelden zum Antworten