Socket-Buffer C vs C++



  • @cooky451
    Hast du Iterator-Debugging deaktiviert? Das ist bei MSVC nämlich per Default an.

    Und wieso soll der Test gegen nullptr "schon richtig so" sein?
    Klar ist er richtig. Er ist halt nur unnötig.



  • hustbaer schrieb:

    Hast du Iterator-Debugging deaktiviert? Das ist bei MSVC nämlich per Default an.

    Ich habe alle security-checks ausgestellt.

    #if _ITERATOR_DEBUG_LEVEL != 0
    #error
    #endif
    

    Wenn ich das einfüge kompiliert es problemlos. (Ich benutze doch aber auch gar keine Iteratoren?)

    hustbaer schrieb:

    Klar ist er richtig. Er ist halt nur unnötig.

    Nicht ganz. 1. ermöglicht es in vielen move-Fällen erst die Optimierung den Destruktor auszulassen (das habe ich in einem anderen C vs C++ Thread hier festgestellt), und 2. ist es generell performanter so oft wie möglich ein call auszulassen.



  • C++ ist immer noch geringfügig langsamer

    Ist auch nicht der gleiche Code

    Buffer[ i ] = (char)( i % 26 + 65 );
    

    vs.

    *p++ = (char)( i % 26 + 65 );
    

    Meine Anmerkungen hoerten nicht bei resize auf.



  • Hat er doch schon selbst korrigiert...



  • Ich habe keine Messwerte gesehen. Meine Erwartungshaltung war, dass sie fettgedruckt irgendwo hervorleuchten. Genauso wie man Behauptungen ins Internet hinausschreit, sollte auch der eigene Irrtum bekanntgegeben werden.

    einfach p[i] schreiben können, anstatt p zu inkrementieren.

    Meiner Erfahrung nach ist *p++ schneller als p[i] . Ich verwende dieses Pattern haufig, wenn Speed im Vordergrund steht. Zaehler und Inkrement wuerde ich auch noch sparen (in dem Beispiel wird er nur fuer Testzwecke gebraucht):

    char *p = Buffer.data();
    char const*  pend = p + Buffer.size();
    while( p != pend ) *p++ = ...;
    

    Omfg: Der Code ist auch wesentlich kuerzer. Zur Leserlichkeit: Ich wuerde ihn auf gleicher Stufe wie vorhergehende Varianten stellen. Daraus folgt: Codefragment ist besser geworden. Hey. 🙂 Und nein, ranged-based-for ist langsamer in VS 2013.

    Aber mal ehrlich: Ist das noch C++ ? Eigentlich lügt man sich doch hier selber in die Tasche. Der std::vector wird hier nur noch zum "Array-Besorger" degradiert und man verwendet weder Iteratoren noch Indizierung um die Performance von C zu erreichen...

    Logo ist das C++, std::vector ist ein Arraybesorger, Zeiger sind Iteratoren.

    Da könnte man doch den vector einfach weglassen und gleich beim char-Array bleiben. Der Unterschied ist eigentlich marginal.

    Nee, der Unterschied ist gewaltig: RAII.



  • knivil schrieb:

    Und nein, ranged-based-for ist langsamer in VS 2013.

    Benchmark?

    knivil schrieb:

    Nee, der Unterschied ist gewaltig: RAII.

    RAII bei Arrays auf dem Stack, klingt ja interessant.



  • @knivil:

    Wenn ich also mein Array in einem Template vergrabe, wie es vector macht, ist es C++ und wenn ich meinen Speicher direkt selbst mit new allokiere und zerstöre ( oder als konstantes Array anlege ), ist es kein C++ ?



  • knivil schrieb:

    Ich habe keine Messwerte gesehen. Meine Erwartungshaltung war, dass sie fettgedruckt irgendwo hervorleuchten. Genauso wie man Behauptungen ins Internet hinausschreit, sollte auch der eigene Irrtum bekanntgegeben werden.

    Ich habe geschrieben, dass jetzt beide Varianten eine identische Laufzeit aufweisen. Musst nur mal alle Beiträge lesen und nicht nur ausgewählte. 😉

    Zudem wollte ich nicht behaupten, sondern ich wollte explizit Hilfe, um meine derzeitige C-Lastigkeit im Bereich Sockets noch etwas einzudämmen und ich wollte dabei sichergehen, dass ich mir da kein Performance-Ei ins Nest lege.
    Außerdem bin ich halt bestrebt, die Kritik anzunehmen und auch, sofern performancetechnisch einwandfrei, C++ intensiver einzusetzen. Ich merke ja selbst bei meinem Quellcode, dass der C++-Anteil nicht immer so hoch ist, wie er sein könnte. Ich arbeite halt viel mit Buffern und co. und da ist C meist näher als C++. Und genau diesen Umstand will ich beseitigen, indem ich in mir selbst die Überzeugung nähre, dass C++ in dem Fall keinen Performancenachteil mit sich bringt.



  • Wenn ich also mein Array in einem Template vergrabe, wie es vector macht, ist es C++ und wenn ich meinen Speicher direkt selbst mit new allokiere und zerstöre ( oder als konstantes Array anlege ), ist es kein C++ ?

    Wie kommst du darauf, beides ist C++, nur nutze ich bei einem RAII. Du must RAII in C++ nicht benutzen, aber das ist der Unterschied.

    Musst nur mal alle Beiträge lesen und nicht nur ausgewählte.

    Das habe ich nicht gemeint. Du must meine Posts verstehen. Mir aber voellig egal.



  • Was ich immernoch nicht verstehe und Cookie wohl auch nicht, ist die Möglichkeit, ein konstantes Char-Array als Member in einer Klasse ( oder halt auf dem Stack ) anzulegen und darauf zu arbeiten? Wieso ist die Variante aus deiner Sicht schlechter als die vector<char>-Variante?



  • @It0101 Mach dir mal keine Sorgen um Arrays auf dem Stack. (Außer wenn sie wie hier 1 MB groß sind :D) Aber wenn dein Code C-Lastig ist dann solltest du einfach mal durch gehen, und an jeder Stelle an der ein Handle (z.B. FILE*, oder auch char* auf reservierten Speicher, oder auch SOCKET) wieder frei gegeben wird diese Freigabe in einen Destruktor schieben.



  • cooky451 schrieb:

    @It0101 Mach dir mal keine Sorgen um Arrays auf dem Stack. (Außer wenn sie wie hier 1 MB groß sind :D) Aber wenn dein Code C-Lastig ist dann solltest du einfach mal durch gehen, und an jeder Stelle an der ein Handle (z.B. FILE*, oder auch char* auf reservierten Speicher, oder auch SOCKET) wieder frei gegeben wird diese Freigabe in einen Destruktor schieben.

    Das mach ich sowieso schon. In der Hinsicht gibts doch auch gar keine Probleme.
    Ich habe mich nur deswegen mal damit auseinandergesetzt, weil hier im Forum immer gleich rumgeheult wird, von wegen: "du darfst das so nicht machen, dass ist kein C++", "new benutzt man nicht, weil man immer Container benutzt", usw... Genau deswegen hab ich mich hingesetzt und überlegt, wie ichs besser machen kann.



  • Wieso ist die Variante aus deiner Sicht schlechter als die vector<char>-Variante?

    Abhaengig vom Anwendungszweck. Allgemein beim Array konstanter Laenge als Member kann ich nicht "moven". Eine Kopie ist noetig, ob mit memcpy oder std::copy ist egal (ich nutze letzteres). Obwohl meist ausreichend flink, ist es kein Vergleich zum Verschieben eines Pointers.

    Ich arbeite halt viel mit Buffern und co. und da ist C meist näher als C++

    Ich auch.

    Benchmark?

    Hier bei mir, aus meiner Erfahrung, bei meinem Problem, ... wenn du Sourcecode sehen moechtest, hier:

    void label::buffer::extract(span::buffer const& buf, label l, span::buffer& out_buf) const
    {
        out_buf.lines_.resize(buf.lines().size());
        out_buf.spans_.clear();
    
        auto pline = buf.lines().data();
        auto pline_end = pline + buf.lines().size();
        auto pline_out = out_buf.lines_.data();
        auto pspan = buf.spans().data();
        auto plabel = labels().data();
    
        for (; pline < pline_end; ++pline)
        {
            auto old_size = out_buf.spans().size();
            auto const pspan_end = pspan + *pline;
            for (; pspan < pspan_end; ++pspan, ++plabel)
            {
                if (*plabel == l) out_buf.spans_.push_back(*pspan);
            }
            *pline_out++ = out_buf.spans().size() - old_size;
        }
    }
    

    Aber ich werde ihn nicht in ein nachvollziehbaren Benchmark aufbereiten.

    RAII bei Arrays auf dem Stack, klingt ja interessant.

    Da steht char-Array, ein Vergleich mit std::vector macht nur Sinn, wenn es dynamisch ist.



  • It0101 schrieb:

    ...

    Vermutlich mache ich ja etwas falsch... Bei mir läuft der C++ Code genauso schnell wie der C-Code. Und das auch wenn ich über einen Index zugreife (Getestet unter Visual Studio 2012).

    #include <iostream>
    #include <array>
    #include <windows.h>
    
    const unsigned Size = 1048576;
    const unsigned Cnt = 1000;
    
    void TestCPP()
    {
        std::array<char, Size> Buffer;
    
        long t1 = GetTickCount();
    
        for(unsigned k = 0; k < Cnt; ++k)
            for(unsigned i = 0; i < Size; ++i)
                Buffer[i] = (char)( i % 26 + 65 );
    
        long t2 = GetTickCount();
        std::cout << "C++: " << t2 - t1 << std::endl;
    }
    ...
    


  • It0101 schrieb:

    Das mach ich sowieso schon. In der Hinsicht gibts doch auch gar keine Probleme.

    Sehr gut.

    It0101 schrieb:

    Ich habe mich nur deswegen mal damit auseinandergesetzt, weil hier im Forum immer gleich rumgeheult wird, von wegen: "du darfst das so nicht machen, dass ist kein C++", "new benutzt man nicht, weil man immer Container benutzt",

    Ja, nur leider hast du hier nicht new mit vector verglichen (der Vergleich macht zumindest begrenzt Sinn), sondern ein Array auf dem Stack mit vector (der Vergleich macht keinen Sinn).



  • Gut, war mein Fehler. Ich hoffe trotzdem, dass ich den Unterschied RAII zwischen C Code in C++ und C++ Code vermitteln konnte. Gewiss gibt es mehr, aber fuer mich ist halt RAII der Knackpunkt. Ich kenne keine andere Sprache, die es aehnlich handhabt.

    Das Rumgeheule kommt daher, dass viele mit Java,C#,C, ... Hintergrund anfangen C++ zu programmieren. Was sie aber nicht tun, da nicht nur Sprachmittel (malloc gegen new) ausgetauscht werden muessen sondern auch Konzepte.



  • Gut, dann sind wir uns ja im Wesentlichen einig. Ich danke euch erstmal für eure Impressionen. Ich werde mal über den vector nachdenken.



  • It0101 schrieb:

    Gut, dann sind wir uns ja im Wesentlichen einig. Ich danke euch erstmal für eure Impressionen. Ich werde mal über den vector nachdenken.

    Wieso beißt du dich eigentlich am std::vector fest, wenn du ein std::array willst (Zumindest deinem C-Code nach, siehe auch dem Code von meinen vorherigen Kommentar)?



  • Da hab ich mich vielleicht etwas doof ausgedrückt.

    Ich wollte eher sagen: "Ich werde die C++-Variante in Zukunft stärker berücksichtigen". Ich beiß mich nicht an vector fest. Array hab ich auch im Hinterkopf. 😉



  • Du darfst natürlich auch in C++ lowlevel programmieren. Es gehört bei C++ zum guten Ton das Ganze wegzukapseln und aufzupassen dass es mit (erkennbar) falschem Input nicht merkwürdig crasht.


Anmelden zum Antworten