Unerklärliche periodische Probleme bei der CPU-Auslastung des Systems auf W2K3E


7

Wir haben einen 64-Bit-Server für Windows 2003 R2 Enterprise, auf dem eine benutzerdefinierte Arbeitslast ausgeführt wird, die unter einem merkwürdigen Leistungsproblem leidet. Die reduzierte Version unten leidet unter einem kleineren Buckel, ist aber qualitativ gleich.

Wir haben es auf eine einfache Trivial-App reduziert, die nichts weiter tut als:

  • auf eine Steckdose hören
  • Beitritt zu einer Multicast-Gruppe
  • Abhören von Paketen, die in dieser Gruppe eingehen
  • Lesen und Verwerfen der Pakete

Die Testanwendung selbst ist eine leicht modifizierte Version des Beispiels für den Boost ASIO-Multicast-Empfänger, sodass nicht wirklich viel schief gehen sollte. Aktueller Code (!) Unten…

Während dieses Programms unter Last ausgeführt wird, wird die CPU für diesen Prozess von Zeit zu Zeit hochgefahren, wobei die gesamte Verarbeitung im Kernel-Code erfolgt:

Perfmon Graph (Hier wird nur CPU 6 angezeigt. Für die Dauer dieses Tests (3h17m) sind alle anderen Prozessoren inaktiv.)

Wie Sie in der Grafik sehen können, geschieht die gesamte Verarbeitungszeit im Kernel-Code, wenn die Lastspitzen auftreten. Die aufgewendete Zeit wird hauptsächlich für verzögerte Prozeduraufrufe (max. 16,8%) und die Behandlung von Interrupts (max. 8,5%) aufgewendet. Es sieht so aus, als würde eine verzögerte Bereinigung stattfinden, aber wir haben keine Ahnung, was es sein könnte.

Soweit wir das beurteilen können, geschieht dies nur auf dem W2K3E-64.

Dies geschieht auf unterschiedlicher Hardware (HS21, HS22, HS22V, HP DL380).

Das Ausführen der Testanwendung unter Windows 2008 zeigt das Problem in viel geringerem Maße (häufiger, aber mit kleineren Buckeln).

Wie können wir das beheben oder wo sollen wir als nächstes suchen?


Aktueller Code aus dem Beispiel:

void handle_receive_from(const boost::system::error_code& error,
    size_t bytes_recvd)
{
    if (!error)
    {
        ++m_receivedPackets;
        m_receivedBytes += bytes_recvd;
        m_last64TotalBytes += bytes_recvd;
        if ( ( m_receivedPackets & 0x3F ) == 0 )
        {
            printf( "Received %u bytes in %u packets. The average size of the last 64 packets was %u bytes, and the last byte received was %x.\n", 
                m_receivedBytes, m_receivedPackets, m_last64TotalBytes / 64, m_buffer[ bytes_recvd - 1 ] );
            m_last64TotalBytes = 0;
        }

        m_socket.async_receive_from(
            boost::asio::buffer(m_buffer, max_length), m_senderEndpoint,
            boost::bind(&receiver::handle_receive_from, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
    else
    {
        std::cerr << "An error occurred when performing an asyncronous read." << std::endl;
        m_socket.get_io_service().stop();
    }
}

Haben Sie eine Überwachung der Ethernet-Karten? Puffergröße? Werden sie voll und geraten in Panik?
Tom O'Connor

Ich glaube nicht, dass der tatsächliche Endbenutzer diese Überwachung eingerichtet hat (wäre die Puffergröße nicht zu detailliert, um sie zu überwachen?), Und ich bin mir ziemlich sicher, dass das Auffüllen des Puffers nicht zu einer so langen Zeit führen würde (20) Minuten!) Leistungshöcker.
MikeyB

War das einzige, was ich an xx denken konnte
Tom O'Connor

Zwischen den Stacheln liegt fast genau eine Stunde. Ist das in Ihren Daten konsistent? Ich würde wahrscheinlich alle Betriebssysteme und TCP-Beschleuniger auf Treiberebene ausschalten und sehen, ob es sich um eine Netz-Treiber-Sache handelt. Warum ist dieser Tag mit win2008 gekennzeichnet?
Markieren Sie

Es sind ziemlich konstante 90 Minuten zwischen den Buckeln. Es wurde mit Windows 2008 markiert, da das Verhalten immer noch angezeigt wird, jedoch in geringerem Maße.
MikeyB

Antworten:


1

"Es sieht so aus, als würde eine verzögerte Bereinigung stattfinden, aber wir haben keine Ahnung, was es sein könnte."

Dies könnte eine Speicherbereinigung sein, aber ich bin nicht sicher, ob die Speicherbereinigung als privilegierte Zeit angezeigt wird. Wenn es sich um eine .NET-Anwendung handelt, können Sie sich die .NET CLR MemoryLeistungsindikatoren ansehen (insbesondere Gen 2 ist teuer).

In diesem Sinne scheint das Erraten möglicher Probleme etwas rückwärts zu sein. Am besten profilieren Sie Ihre Anwendung und sehen, was sie währenddessen tut, um zu sehen, welche Anrufe die Anwendung tätigt. Möglicherweise können Sie nur den Prozessmonitor verwenden , um die Systemaufrufe zu überwachen.


1
Der fragliche Code ist c ++, nicht .NET. Ich habe eine Art Garbage Collection auf Betriebssystemebene theoretisiert.
MikeyB

1

Ich gehe davon aus, dass das System Multicast-Pakete empfängt. Können Sie versuchen, zu verhindern, dass die Pakete empfangen werden, und feststellen, ob das gleiche Problem auftritt?

Wie wäre es, der Multicast-Gruppe beizutreten, aber dann nicht auf Pakete zu warten?

Sie sagen, es passiert auf verschiedenen Systemen, aber was ist mit der tatsächlichen NIC-Hardware? Es ist möglich, dass es auf diesen verschiedenen Systemen gleich ist.

Update: Wenn alle Systeme Broadcom-Netzwerkkarten verwenden, liegt das Problem möglicherweise an der Netzwerkkarte. Insbesondere die von Microsoft bereitgestellten Broadcom-Treiber sind mies; Die auf der Broadcom-Website sind viel besser.


Wenn keine Pakete empfangen werden, bleibt alles flach. Wenn wir die Paketrate verdoppeln, verdoppelt sich die Amplitude der Buckel. Es wurde nur Broadcom-Hardware (verschiedene Chipsätze) ausprobiert.
MikeyB

2
@ MikeyB: Welche Treiber verwenden Sie? Die von Microsoft bereitgestellten Broadcom-Treiber sind schrecklich. Laden Sie die Treiber von der Broadcom-Website herunter.
Wfaulk

0

Sie können sich zwei Dinge ansehen: Ihr Thread-Quantum und die Ursachen Ihres DPC (verzögerte Prozeduraufrufe).

Thread-Quanten sind sehr einfach zu adressieren (wahrscheinlich ein roter Hering, können aber auch überprüft werden);

  1. Klicken Sie mit der rechten Maustaste auf Arbeitsplatz
  2. Wählen Sie Eigenschaften
  3. Wählen Sie die Registerkarte Erweitert
  4. Wählen Sie unter Leistung "Einstellungen ..."
  5. Wählen Sie in den neuen Fenstern die Registerkarte Erweitert (jetzt sind wir DOPPELT erweitert!)
  6. Welche ist unter Prozessorplanung ausgewählt? "Programme" oder "Hintergrunddienste"?

Am wahrscheinlichsten ist Hintergrunddienste ausgewählt. Versuchen Sie, Programme auszuwählen. Dadurch wird die Zeit zwischen Interrupts verkürzt und es können mehr Threads in derselben Zeit auf dem Prozessor ausgeführt werden. Sie erhalten mehr Interrupts, aber weniger Verarbeitungszeit.

Verzögerte Prozedur Anrufe sind etwas schwieriger zu diagnostizieren.

Wie von @wfaulk angegeben, weist dies normalerweise auf ein Treiberproblem hin. Es gibt ein praktisches Tool namens DPC Latency Checker, mit dem Sie diese Probleme diagnostizieren können. Auch wenn dies auf mehreren Hardwareplattformen geschieht, haben alle möglicherweise einen gemeinsamen Treiber. Führen Sie DPC Checker aus und befolgen Sie die Anweisungen auf ihrer Website.

Drei Anschlussfragen:

  1. Verwenden Sie Teamed-NICs? Sie verwenden den TCP / IP-Stack, um miteinander zu kommunizieren, und können schwerwiegende DPC-Probleme verursachen.

  2. Unterstützen Ihre Netzwerkkarten TCP Offload? Ist es aktiviert?

  3. (Eine vollständige Aufnahme im Dunkeln) Ist Ihr Testserver Teil einer Domain? Gruppenrichtlinienobjekte werden standardmäßig alle 90 Minuten aktualisiert ...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.