Könnten fstreams schneller als FILE * sein?



  • Bashar schrieb:

    GPC: Die Frage trägt doch die Antwort schon in sich. Wäre der Geschwindigkeitsvorteil praktisch nicht umsetzbar, wäre er auch theoretisch nicht vorhanden. 😉

    Ist ein Argument ^^
    Aber du weißt ja, in der Informatik ist theoretisch vieles möglich, nur praktisch noch nicht 😃

    Sagen wir mal so: Ich hab aber keine Ahnung von den tieferen Details und zweifle mal vorsichtshalber die Prämisse des ganzen an: SIND sie denn wirklich langsamer? Auch bei einem optimierenden Compiler?

    Ich kann natürlich nicht für jeden Fall sprechen, aber erst kürzlich gab's wieder einen Thread dazu ( ab Seite 2 bzw. 3 wird's interessant) und ich machte die Erfahrung auch schon selber. Ich komme nur gerade darauf, weil ich mit Xin darüber diskutiert habe, dem das auch so geht, dass die FILE* schneller sind.

    Wäre es auch möglich, dass die Verwendung von std::string einen (deutlichen) Performanceunterschied mit sich bringt? Ich denke eher nicht, jedenfalls nicht, wenn man sich nicht ungeschickt anstellt.



  • Artchi schrieb:

    Bei FILE kann ich mir vorstellen, das es keinen Puffer gibt, das was ich schreibe, landet sofort beim nativen API.

    stdio ist natürlich auch gepuffert. Da das OS selbst nochmal puffert und die meisten IO-Geräte (Platten) auch nochmal liegt der Grund hauptsächlich in der Vermeidung unzähliger überflüssiger Systemaufrufe. Die Existenzberechtigung von stdio ist von einem bestimmten Standpunkt aus gesehen in erster Linie die Bereitstellung von gepufferter Ein/Ausgabe. Das ganze noch in ein hübsches Interface gepackt, dazu noch formatierte Ein/Ausgabe ala printf/scanf und fertig.

    iostream ist im Grunde das gleiche, nur zum einen objektorientiert, und zum anderen liegt die Implementierung offener, da man die Streams von den Puffern getrennt hat, und jederzeit einem Stream einen anderen, auch selbstgeschriebenen, Puffer unterschieben kann, was bei der stdio nicht geht. Der OS-Anteil liegt dabei nur an dem, was passiert, wenn der Puffer voll (Ausgabe) bzw. leer (Eingabe) ist. Es gibt aber auch hier keinen Grund, warum bei stdio was anderes passieren sollte als bei iostream.



  • Bashar schrieb:

    Der OS-Anteil liegt dabei nur an dem, was passiert, wenn der Puffer voll (Ausgabe) bzw. leer (Eingabe) ist. Es gibt aber auch hier keinen Grund, warum bei stdio was anderes passieren sollte als bei iostream.

    bei windoze z.b. gibt's mehr als nur eine systemfunktion, um was auf'n datenträger zu bringen. zudem kannste bei WriteFile etc. noch 'ne menge options mitgeben. ein popeliges flag, welches z.b. eine 'fstream'-implementation beim aufruf so'ner systemfunktion anders setzt als die 'FILE*' funktionen das machen... und schon ist einer schneller als der andere...



  • fstream muss oft andere Dinge tun als FILE*, die auch z.T. threadsafe zu passieren haben, z.B. der Zugriff die globale locale. Das bremst. Enorm. Davon abgesehen begreife ich nicht was die Leute so an den iostreams fasziniert, das Interface ist doch der komplette Schrott.



  • hustbaer schrieb:

    Davon abgesehen begreife ich nicht was die Leute so an den iostreams fasziniert, das Interface ist doch der komplette Schrott.

    die finden eben die überladenen shift-operatoren so toll 😉



  • Manche schätzen auch die Tatsache, dass die Typen zur Compile-Zeit feststehen und daher kein Zwang besteht, diese zur Laufzeit aus einem Formatstring "herauszupopeln".



  • hustbaer schrieb:

    Davon abgesehen begreife ich nicht was die Leute so an den iostreams fasziniert, das Interface ist doch der komplette Schrott.

    Klar ist es etwas gewöhnungsbedürftig (gerade), aber immer noch deutlich besser (und sicherer) als das printf()/scanf()-Gebastel.



  • hustbaer schrieb:

    Davon abgesehen begreife ich nicht was die Leute so an den iostreams fasziniert, das Interface ist doch der komplette Schrott.

    Hallo Hustbaer,

    könntest Du das bitte begründen. Was genau am iostream-Interface ist warum Schrott?
    Ich wäre dankbar für eine konstruktive Antwort.

    Gruß
    Werner



  • net schrieb:

    bei windoze z.b. gibt's mehr als nur eine systemfunktion, um was auf'n datenträger zu bringen. zudem kannste bei WriteFile etc. noch 'ne menge options mitgeben. ein popeliges flag, welches z.b. eine 'fstream'-implementation beim aufruf so'ner systemfunktion anders setzt als die 'FILE*' funktionen das machen... und schon ist einer schneller als der andere...

    Das wär dann aber eher ein zufälliger Performance-Unterschied. Inwiefern hängt denn die Wahl der Systemfunktion davon ab, ob grad ein streambuf oder ein _filebuf geflusht werden soll?

    BTW mal an die letzte Entwicklung, die dieser Thread genommen hat:
    Das Interface für die formatierte Ein/Ausgabe ist ja gut und schön, aber auch nicht wirklich zwischen stdio und iostream vergleichbar. Ich hatte den Thread so verstanden, dass die Performance unterschiedlich ist, wenn man unformatiert, also zeichen- oder zeilenweise arbeitet.



  • Bashar schrieb:

    Ich hatte den Thread so verstanden, dass die Performance unterschiedlich ist, wenn man unformatiert, also zeichen- oder zeilenweise arbeitet.

    Ja, so hatte ich das auch gemeint. Interface ist mir in dem Punkt völlig egal.



  • Werner Salomon schrieb:

    könntest Du das bitte begründen. Was genau am iostream-Interface ist warum Schrott?
    Ich wäre dankbar für eine konstruktive Antwort.

    eventuell open/close. eventuell überhaupt die möglichkeit kaputter streams. vielleicht zu viel formatierungszeugs. eventuell ein komischer eingabeoperator, der verlangt, daß man vorher ein eigenes kaputtes objekt anlegt.



  • @volkard
    Wenn ich mich recht erinnere, warst du doch auch immer der Meinung, fstreams könnten schneller sein, oder nicht? Dir fallen doch bestimmt auch ein paar Sätze dazu ein...



  • Was den fstreams im Textmodus noch fehlt, ist die Rechtschreibprüfung in Hochgeschwindigkeit! 😃



  • könntest Du das bitte begründen. Was genau am iostream-Interface ist warum Schrott?

    Ein basic_streambuf Objekt hat eine locale - das macht keinen Sinn, zuunterst sollte etwas stehen was rein raw-io macht und nix von locales weiss -> sinnlose dependancy. Überhaupt ist das ganze basic_streambuf Interface IMHO unsauber, Input und Output schon auf unterster Ebene vermischt, weiter oben werden dann aber reine Input und reine Output Streams angeboten, huh? Die in und out Streams sind weitestgehend getrennt (z.B. unabhängig positionierbar), trotzdem pappt man as in ein Interface zusammen. Dann die Vermischung von Buffering und IO auf unterster Ebene - macht auch wenig Sinn.

    Dann die vermischung von "streams" (z.B. Sockets, Drucker, ...) und "random access IO" (Files, Memory-Buffer, ...), und wie schon erwähnt die Vermischung von Input-Only, Output-Only und Input/Output "streams" (bzw. "files"). Für soetwas sollte es getrennte Interfaces geben, und dann eben passende Adapter mittels denen ich aus einem "file" einen "stream" machen kann oder was auch immer.

    Also kurz: Die Trennung von IO, Buffering und "Formating" ist IMHO ungenügend, unsauber und unübersichtlich. Oder was volkard schon angesprochen hat, die ganzen State-Bits. Wieso gibts nicht eine Exception wenn ich was lesen will was nichtmehr da ist?

    Und dann die ganzen Namen OMG. "stossc", ja klar, versteht jeder auf Anhieb.

    ----

    Mit iostreams zu Arbeiten verbietet sich für mich in allen Fällen wo ich mehr machen muss/will als einfach bloss ein paar Strings/Zeichen in ein File zu schreiben bzw. zu lesen. Bevor ich mich tagelang mit iostreams rumärgere bei dem Versuch nen Socket, ein Stück NVRAM oder eine Serielle Schnittstelle mit streams zusammenzuknoten gehe ich lieber her und definiere meine eigene kleine Klassenhierarchie.



  • Oder was volkard schon angesprochen hat, die ganzen State-Bits. Wieso gibts nicht eine Exception wenn ich was lesen will was nichtmehr da ist?

    Also Exceptions gibts ja in der stream lib, die mußt du aber dummerweise vorher einmal explizit einschalten, dann bekommst du deine Exceptions. Ist aus Kompatibilitätsgründen leider so, das die Statebits standardmäßig herhalten. Aber es gibt Exceptions.

    gehe ich lieber her und definiere meine eigene kleine Klassenhierarchie.

    Verbietet dir ja auch keiner. Aber vielleicht hilft das hier ja auch etwas:
    http://www.boost.org/libs/iostreams/doc/index.html



  • hustbaer schrieb:

    Also kurz: Die Trennung von IO, Buffering und "Formating" ist IMHO ungenügend, unsauber und unübersichtlich.

    👍



  • Wie FILE * und iostreams schreiben oder lesen, spielt eigentlich keine Rolle, denn in beiden Fällen greift man auf das OS zurück und wie das diese Aufgaben erledigt, kann der Programmierer sowieso nicht beeinflussen.

    Die Frage stellt sich also ausschließlich in dem Bereich, solange man in C/C++ herumfrickelt.
    File-Streams sind in meinen Augen "gefühlt" schneller. Warum "gefühlt"? Weil ich nicht jedes Programm zweimal schreibe, nur um herauszufinden, was schneller ist.
    Also überlegen wir uns einfach mal was praktisches.

    Jeder Operator ist eine Funktion, ob sie nun "Schiebe( irgendwas )" oder "operator <<( irgendwas )" heißt, spielt dabei erstmal keine Rolle, Funktion ist Funktion, auch wenn sie operator heißt.

    Funktionen muss man rufen, Also Daten auf'n Stack packen, Register sichern, in die Funktion springen, Daten aus dem Stack holen, Ausgeben, Zurückspringen, Register zurücksetzen, Stack zurücksetzen.

    std::cout << "Hallo Welt" << std::endl;
    

    ist ein Ausdruck mit zwei Operatoren, also erstmal minimum 2 Funktionsaufrufe:

    operator << (std::out, "Hallo Welt" );
    operator << (std::out, std::endl );
    

    Diese Funktionsaufrufe sind freundlicherweise nicht virtuell. Immerhin etwas. Trotzdem punktet die Variante mit dem FILE * hier erstmal.

    printf( "%s\n", "Hello Welt" );
    

    Ein Funktionsaufruf, kopiert einen String auf die Ausgabe jedesmal, wenn man ein '%' entdeckt, wird statt des Strings das entsprechende Argument ausgedruckt.
    Die Umwandlung von (int) nach (char 😉 müssen beide übernehmen, von daher ändert sich hier auch nichts, was die Ausgabe angeht.

    Statt 1 Funktionsaufrufe bei printf() stehen also zwangsweise und unveränderlich x Funktionsaufrufe bei den IOStreams da. Da ist also auch nix dran zu verbessern. Aber nehmen die wirklich viel Zeit in Anspruch?

    Eigentlich nicht... aber wer benutzt bei iostreams schon Char-Arrays?
    Stattdessen vielleicht eher Objekte wie std::string, die nicht einfach wie bei scanf() beschrieben werden, sondern ordentlich per Konstruktor( noch ein Funktionsaufruf... ) erzeugt werden, dann Speicher besorgen ( Systemcall... ) und beim Verlassen des Kontext wieder per Destruktor zerstört werden ( Funktionsaufruf und SystemCall... ).

    Natürlich kann man einen std::string wie ein char-Array auch wiederverwenden, aber dann muss die Größe überprüft werden, ob der neue Inhalt überhaupt da reinpasst, gegebenenfalls neuer Speicher angefordert werden (Systemcall...) und der alte freigegeben werden (Systemcall...).

    scanf() packt die Daten in ein Array und fertig. Für das Ziel ist kein Call erforderlich, für die Quelle wird für's lesen genauso ein SystemCall erforderlich, wie beim IOStream.

    Hier geht massiv Geschwindigkeit verloren, dafür gewinnt man Sicherheit.

    Fazit: Wer einfache Routinen schreibt, mal eben was ausgeben will, ist mit printf() gut bedient. Wer komplexe Sachen schreiben möchte und nicht ganz sicher ist, dass er das mit scanf() und readf() usw. richtig hinbekommt, für den sind die iostreams sehr empfehlenswert.

    Lieber langsam als falsch.
    Der Vorteil bei den IOStreams ist wohl eher in der Lesbarkeit des Codes zu sehen. Der Nachteil dabei, dass der Formatstring verloren ging und die Sache etwas langsamer wird.

    Aber es ist in meinen Augen technisch absolut unmöglich, dass iostreams jemals so schnell wird, wie FILE *.

    Wie immer gilt, was besser ist, bestimmt das Geschick des Programmierers und die Anwendung, die er zu schreiben hat.

    PS: Ich bitte mein Posting wohlwollend aufzunehmen, dank diesem Posting habe ich jetzt meine EBay Auktion verpasst *grummel*



  • Nach meinen Überlegungen müsste eigentlich iostream schneller sein, als printf. Um z. B. einen int auszugeben, rufe ich mit printf eine Funktion auf. Diese parst erst mal den Formatstring. Und genau das kostet Zeit. Mit dem ostream-Operator für int wird direkt die richtige Routine angesprungen. Das gilt um so mehr, je mehr ich ausgebe.

    Andererseits stimmt das nicht so ganz mit den iostreams. Die Routine, die angesprungen wird, schreibt ja nicht direkt auf den Filedeskriptor, sondern in ein std::streambuf. Und erst diese führt die Ausgabe durch.

    Das bietet allerdings einen enormen Vorteil: der std::streambuf muß kein Filedeskriptor sein, sondern ist austauschbar.

    Ich muß allerdings zugeben, auch wenn ich ein Anhänger von iostreams bin, das das Interface tatsächlich nicht so glücklich ist.

    Übrigens habe ich mal einen Test unter Solaris (fragt mich nicht nach Version oder Ausstattung) gemacht. Da war printf geringfügig schneller, was ich verwunderlich fand. Ich kann mir das nur so erklären, daß printf einfach hoch optimiert ist. Der Parser für den Formatstring ist möglicherweise in hochoptimierten Assembler geschrieben, da er sehr oft verwendet wird.

    Tntnet



  • Ich persönlich bin mit iostream noch nie wegen der Performance gegen die Wand gefahren.
    Was sind denn das für Situationen in denen iostream zu langsam ist?
    1998 ,als nen PC 400 Mhz und 64MB RAM hatte, ist jeder gut mit den stream Klassen klar gekommen.8 Jahre später,wo die Prozessoren 10 mal schneller sind, fällt auf einmal Gott und der Welt auf wie schlecht und langsam doch die stream Klassen sind? 😕
    Ich mach mir lieber über andere (wichtige) Dinge Gedanken.
    Die ganze Diskussion sieht für mich eher nach ner Mischung aus Langeweile und der aktuellen Tendenz ,aus C++ ne Wissenschaft zu machen, aus.

    Gruß Spacelord



  • Xin schrieb:

    PS: Ich bitte mein Posting wohlwollend aufzunehmen, dank diesem Posting habe ich jetzt meine EBay Auktion verpasst *grummel*

    Schon wieder 'n Regal weg *SCNR* 😃 😉 ?

    Spacelord schrieb:

    Was sind denn das für Situationen in denen iostream zu langsam ist?

    Wie du als aufmerksamer Leser sicherlich bemerkt hast, ging es darum herauszufinden, wieso fstreams (+std::string) normalerweise etwas langsamer als FILE * sind und ob man das umkehren könnte. Kein einziger Post hat "fstreams sind zu langsam" als Inhalt.


Anmelden zum Antworten