unbuffered streams
-
Werner Salomon schrieb:
.. da verstehe ich nicht, was Du damit sagen willst

Wenn ich dein Streambuf mit einer ungenerischen Ad-Hoc-Lösung vergleiche ist bei deine ungemein langsamer:
void parse1(std::istreambuf_iterator<char> it, std::istreambuf_iterator<char> end, std::ostream& out, std::array<char, 64> const& arr) { out << "Format 1\n"; std::ostreambuf_iterator<char> o(out); std::copy(arr.begin(), arr.end(), o); std::copy(++it, end, o); } void parse2(std::istreambuf_iterator<char> it, std::istreambuf_iterator<char> end, std::ostream& out, std::array<char, 64> const& arr) { out << "Format 2\n"; std::ostreambuf_iterator<char> o(out); std::copy(arr.begin(), arr.end(), o); std::copy(++it, end, o); } void parse(std::istream& in, std::ostream& out) { std::istreambuf_iterator<char> it(in), end; std::array<char, 64> save; std::copy_n(it, 64, save.begin()); int magic = 17; for (int i=0; i<64; ++i) magic = 13*magic + save[i]; if (magic%2) parse1(it, end, out, save); else parse2(in, end, out, save); }(das ist so in etwa, was ich von Meep² verstanden habe)
Vollständiger Vergleich: http://ideone.com/Tl3y8K
In meinen Messungen ergibt sich:# Ad-Hoc-Hack: real 0m0.168s user 0m0.000s sys 0m0.304s # Reserve=1 real 0m3.519s user 0m3.352s sys 0m0.296s # Reserve=1<<16 real 0m1.971s user 0m1.840s sys 0m0.252sDass deine Variante so langsam ist, hätte ich nicht gedacht, vielleicht habe ich da etwas falsch gemacht.
In diesem Fall wären -- wie auch hustbaer meint -- zwei Strategien angebracht, also ein "Streambuf [...] der selbständig die Strategie wechselt" (mein Post vorher).
-
werni schrieb:
Dass deine Variante so langsam ist, hätte ich nicht gedacht, vielleicht habe ich da etwas falsch gemacht.
Na ja - IMHO hast Du hier Äpfel mit Birnen verglichen. Das fängt schon damit an, dass Deine 'Ad-hoc-Lösung' keine Lösung ist. Zumindest hat der Anwender am Ende keinen Stream sondern ein Stück boost::array<64> plus einen Stream, wo er sich seine Sachen heraus pfrimeln darf. Stell Dir vor, da steht ab Position 62 bis Position 68 eine Zahl, die als solche geparst werden soll - das ist doch nur aufwendig. Diesen Aufwand hast Du nicht mit berechnet.
Ansonsten parst Du ja gar nicht, sondern machst nur ein Byte-Copy nach cout.Ich habe mit selber so einen Test geschrieben, mit einem Buffer (im Memory!) mit 100kByte etwa zur Hälfte mit Text und zur anderen Hälfte mit Zahlen gefüllt. Wenn ich den
BufferN<>zwischen istream und der eigentlichen Quelle setze, so verliert das Programm ca. 10% an Geschwindigkeit und absolut 1ms auf 100kByte. Dabei lese ich die Zahlen und überlese mitignoredie Texte. Wenn die Quelle jetzt eine Socket-Verbindung wäre, würde der relative Anteil noch weiter zurückgehen, da die Zeit für den Netz-Verkehr noch hinzukommt.Und wem diese 1ms immer noch zu viel Zeitverlust sind, der kann einfach nach dem (zweiten und endgültigem) Lesen der ersten 64-plus-ein-paar-Bytes den Streambuf wieder zurück setzen. Man muss nur aufpassen einen Zeitpunkt zu wählen, bei dem beide Streambufs (Wrapper und Quelle) synchron sind - sich also keine ungelesenen Bytes im Wrapper befinden, die der Quelle bereits entzogen wurden. Das kann man prüfen, indem man die noch ausstehenden Bytes abfragt.
Etwa so:if( in.rdbuf()->in_avail() == 0 ) // in := istream; aktuell mit dem Wrapper { in.rdbuf( &src ); // src := Quelle; streambuf umschalten }und mit dieser Methode lässt sich überhaupt kein Performanceunterschied mehr feststellen.
Gruß
Werner