Daten über einen socket mit recv empfangen führt zu 100% cpu last



  • Neue Infos:

    Das abschalten des AV-Programmes (Email-Scan) hat schon viel gebracht 😡
    Das zusammen mit den Optimierungen führt dazu, dass die CPU Last über 30% nicht hinauskommt.

    Dafür ist die Übertragungsrate nun bei nur 1.2MB/Sek.
    Wenn ich 8 Threads verwende komme ich auf 4-6MB dafür ist die CPU Last dann wieder bei 100% (30*80=100)?

    Nachtrag: Das Problem wird durch

    m_RecvBuffer += buffer;
    

    verursacht. Ich dachte nicht, dass dies so viel ausmachen würde. Naja.

    Wie umgehe ich das am schlauesten? Kann man speicherbereiche erweitern? Quasi immer die 10KB hinten dranhängen?

    Stefan



  • ich gehe mal davon aus dass m_RecvBuffer auch ein CString ist. und CString ist für "stückerlweise immer länger machen" nicht gerade optimal geeignet.

    als "quick fix" kannst du probieren den CString gleich von anfang an gross genug zu machen, z.B. mit m_RecvBuffer.Preallocate(1024 * 1024).

    oder exponentiell wachsen lassen:

    if (m_RecvBuffer.GetAllocLength() < (m_RecvBuffer.GetLength() + sizeof(buffer) + 1))
        m_RecvBuffer.Preallocate(m_RecvBuffer.GetAllocLength() * 2);
    m_RecvBuffer += ...;
    

    ich würde das ganze aber etwas anders angehen - wozu du allerdings mehr umschreiben müsstest.
    ich würde vielleicht erstmal alles in zeilen zerteilen. in der art:

    class foo
    {
    public:
        foo() :
            m_carriage_return_seen(false)
        {
        }
    
        void push(char const* begin, char const* end)
        {
            while (begin != end)
            {
                push(*begin);
                ++begin;
            }
        }
    
        void push(char ch)
        {
            m_buffer.push_back(ch);
    
            if (m_carriage_return_seen && ch == '\n')
            {
                emit_line();
                m_buffer.clear();
            }
    
            m_carriage_return_seen = (ch == '\r');
        }
    
        void emit_line()
        {
            // m_buffer enthält jetzt genau eine zeile text
            // hier sollte diese zeile jetzt ans nächste glied in der kette weitergereicht werden
        }
    
    private:
        std::vector<char> m_buffer;
        bool m_carriage_return_seen;
    }
    

    dadurch musst du nicht jedes mal alle bereits empfangenen bytes erneut nach einem zeilenumbruch durchsuchen, was einiges an zeit spart.

    in der emit_line() funktion leitest du das dann z.b. weiter an eine andere klasse, die sich ums IMAP protokoll ansich kümmert, und die z.b. auf eine zeile in einem bestimmten format wartet.
    dazu musst du auch kein "find" verwenden - die meisten protokolle sind so aufgebaut, dass man die "haben fertig" zeilen sehr einfach erkennen kann. zumindest die die ich kenne.

    beispiel:

    void bar::push_line(char const* begin, char const* end)
    {
        m_reply_lines.push_back(std::string(begin, end));
    
        size_t const line_size = end - begin;
    
        // erster check, einfach, für schnelle "rejection" der meisten unpassenden zeilen
        if (line_size >= 5
            && begin[0] == 'I'    // nur ein beispiel, ich hab keine ahnung vom IMAP protokoll
            && begin[1] == 'M'
            && begin[2] == 'A'
            && begin[3] == 'P'
            && begin[4] == '_')
        {
            // genauer check ob es die gesuchte zeile ist
            if (...)
            {
                process_command_reply();
                m_reply_lines.clear();
            }
        }
    }
    

    ich will damit nur grob ne richtung andeuten, wie man halbwegs schnell und halbwegs sauber (und IMO mit vertretbarem aufwand) zeilenbasierte protokolle parsen kann.

    ich hoffe du kannst damit was anfangen.



  • Hallo,

    ich habes gefunden. Es ist ein CString::Trim("\r\n ").
    Wenn diesen Befehl auf einen 23MB String losläßt dauert das 15Sekunden.
    QuadCore 3GHz, 8GB RAM, 64Bit OS. Ramdurchsatz ca. 32GByte/Sekunde

    Ich wußte ja das CString nicht so schnell ist, aber das ist doch lächerlich.

    Ich lese nun direkt in den Buffer des CString mittels GetBufferSetLength und ReleaseBuffer. Wenn der Buffer zu klein wird kopiere ich ihn in einen doppelt so großen. Das optimiere ich dann später.

    Bei RecvIntoBuffer lese ich nun solange Daten kommen mit einen Select Timeout von 250ms.

    while (SocketReadable(m_Socket) == TRUE)
    {
    }

    Vielen Dank für Eure Hilfe!
    Das hätte ich so wohl nicht gefunden!

    Stefan

    PS: ich mag keine Klartextprotkolle!



  • Klartextprotokolle sind das Beste wo gibt 🙂



  • Ramdurchsatz ca. 32GByte/Sekunde

    Gerücht!



  • hustbaer schrieb:

    Klartextprotokolle sind das Beste wo gibt 🙂

    Sagt Jemand der eine Taschenlampe für ein 500 Euro Smartphone programmiert hat :xmas2:



  • StefanKittel schrieb:

    hustbaer schrieb:

    Klartextprotokolle sind das Beste wo gibt 🙂

    Sagt Jemand der eine Taschenlampe für ein 500 Euro Smartphone programmiert hat :xmas2:

    Von mir ist nur der Windows Port 😉

    BTW: doch kein Gerücht. Hab mich grad schlau gelesen. Wahnsinn. Will auch einen i7 🙂



  • hustbaer schrieb:

    Klartextprotokolle sind das Beste wo gibt 🙂

    Du bist altmodisch.
    Das heisst: "Klartextprotokoll sind s'bescht, wos je häts gits." (ca. 3:50)

    @hustbaer
    Ich finde es wahnsinnig, wie Konsistent sich dein Programm auf den verschiedenen System verhält. Wie kriegst du das nur hin, dass gleich aussieht? :p



  • drakon schrieb:

    @hustbaer
    Ich finde es wahnsinnig, wie Konsistent sich dein Programm auf den verschiedenen System verhält. Wie kriegst du das nur hin, dass gleich aussieht? :p

    In der Tat. Pixelgenau gleich.

    D:\Downloads>fc screen-java-windows.png screen-java-linux.png
    Vergleichen der Dateien screen-java-windows.png und SCREEN-JAVA-LINUX.PNG
    FC: Keine Unterschiede gefunden
    
    D:\Downloads>fc screen-java-windows.png screen-java-macosx.png
    Vergleichen der Dateien screen-java-windows.png und SCREEN-JAVA-MACOSX.PNG
    FC: Keine Unterschiede gefunden
    

    Will auch einen i7.



  • volkard schrieb:

    drakon schrieb:

    @hustbaer
    Ich finde es wahnsinnig, wie Konsistent sich dein Programm auf den verschiedenen System verhält. Wie kriegst du das nur hin, dass gleich aussieht? :p

    In der Tat. Pixelgenau gleich.

    Phu.. Ich habe es vermutet, aber das es wirklich so gleich ist, hätte ich nie erwartet..


Anmelden zum Antworten