CPU0 ist mit Eth1-Interrupts überfüllt

12

Ich habe eine Ubuntu-VM, die in Ubuntu-basiertem Xen XCP ausgeführt wird. Dahinter befindet sich ein benutzerdefinierter FCGI-basierter HTTP-Dienst nginx.

Unter Last ist ab der erste CPU-Kern gesättigt und der Rest ist unterlastet.

In /proc/interruptsdem sehe ich CPU0 dient eine Größenordnung mehr Unterbrechungen als jeder anderer Kern. Die meisten von ihnen kommen aus eth1.

Kann ich irgendetwas tun, um die Leistung dieser VM zu verbessern? Gibt es eine Möglichkeit, Interrupts gleichmäßiger auszugleichen?


Gory Details:

$ uname -a
Linux MYHOST 2.6.38-15-virtual # 59-Ubuntu SMP Fr 27 Apr 16:40:18 UTC 2012 i686 i686 i386 GNU / Linux

$ lsb_release -a
Es sind keine LSB-Module verfügbar.
Händler-ID: Ubuntu
Beschreibung: Ubuntu 11.04
Veröffentlichung: 11.04
Codename: natty

$ cat / proc / interrupts 
           CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7       
283: 113720624 0 0 0 0 0 0 0 xen-dyn-event eth1
284: 1 0 0 0 0 0 0 0 xen-dyn-event eth0
285: 2254 0 0 3873799 0 0 0 0 xen-dyn-event blkif
286: 23 0 0 0 0 0 0 0 xen-dyn-event hvc_console
287: 492 42 0 0 0 0 0 295324 xen-dyn-event xenbus
288: 0 0 0 0 0 0 0 222294 xen-percpu-ipi callfuncsingle7
289: 0 0 0 0 0 0 0 0 xen-percpu-virq debug7
290: 0 0 0 0 0 0 0 151302 xen-percpu-ipi callfunc7
291: 0 0 0 0 0 0 0 3236015 xen-percpu-ipi resched7
292: 0 0 0 0 0 0 0 60064 xen-percpu-ipi spinlock7
293: 0 0 0 0 0 0 0 12355510 xen-percpu-virq timer7
294: 0 0 0 0 0 0 803174 0 xen-percpu-ipi callfuncsingle6
295: 0 0 0 0 0 0 0 0 xen-percpu-virq debug6
296: 0 0 0 0 0 0 60027 0 xen-percpu-ipi callfunc6
297: 0 0 0 0 0 0 5374762 0 xen-percpu-ipi resched6
298: 0 0 0 0 0 0 64976 0 xen-percpu-ipi spinlock6
299: 0 0 0 0 0 0 15294870 0 xen-percpu-virq timer6
300: 0 0 0 0 0 264441 0 0 xen-percpu-ipi callfuncsingle5
301: 0 0 0 0 0 0 0 0 xen-percpu-virq debug5
302: 0 0 0 0 0 79324 0 0 xen-percpu-ipi callfunc5
303: 0 0 0 0 0 3468144 0 0 xen-percpu-ipi resched5
304: 0 0 0 0 0 66269 0 0 xen-percpu-ipi spinlock5
305: 0 0 0 0 0 12778464 0 0 xen-percpu-virq timer5
306: 0 0 0 0 844591 0 0 0 xen-percpu-ipi callfuncsingle4
307: 0 0 0 0 0 0 0 0 xen-percpu-virq debug4
308: 0 0 0 0 75293 0 0 0 xen-percpu-ipi callfunc4
309: 0 0 0 0 3482146 0 0 0 xen-percpu-ipi resched4
310: 0 0 0 0 79312 0 0 0 xen-percpu-ipi spinlock4
311: 0 0 0 0 21642424 0 0 0 xen-percpu-virq timer4
312: 0 0 0 449141 0 0 0 0 xen-percpu-ipi callfuncsingle3
313: 0 0 0 0 0 0 0 0 xen-percpu-virq debug3
314: 0 0 0 95405 0 0 0 0 xen-percpu-ipi callfunc3
315: 0 0 0 3802992 0 0 0 0 xen-percpu-ipi resched3
316: 0 0 0 76607 0 0 0 0 xen-percpu-ipi spinlock3
317: 0 0 0 16439729 0 0 0 0 xen-percpu-virq timer3
318: 0 0 876383 0 0 0 0 0 xen-percpu-ipi callfuncsingle2
319: 0 0 0 0 0 0 0 0 xen-percpu-virq debug2
320: 0 0 76416 0 0 0 0 0 xen-percpu-ipi callfunc2
321: 0 0 3422476 0 0 0 0 0 xen-percpu-ipi resched2
322: 0 0 69217 0 0 0 0 0 xen-percpu-ipi spinlock2
323: 0 0 10247182 0 0 0 0 0 xen-percpu-virq timer2
324: 0 393514 0 0 0 0 0 0 xen-percpu-ipi callfuncsingle1
325: 0 0 0 0 0 0 0 0 xen-percpu-virq debug1
326: 0 95773 0 0 0 0 0 0 xen-percpu-ipi callfunc1
327: 0 3551629 0 0 0 0 0 0 xen-percpu-ipi resched1
328: 0 77823 0 0 0 0 0 0 xen-percpu-ipi spinlock1
329: 0 13784021 0 0 0 0 0 0 xen-percpu-virq timer1
330: 730435 0 0 0 0 0 0 0 xen-percpu-ipi callfuncsingle0
331: 0 0 0 0 0 0 0 0 xen-percpu-virq debug0
332: 39649 0 0 0 0 0 0 0 xen-percpu-ipi callfunc0
333: 3607120 0 0 0 0 0 0 0 xen-percpu-ipi resched0
334: 348740 0 0 0 0 0 0 0 xen-percpu-ipi spinlock0
335: 89912004 0 0 0 0 0 0 0 xen-percpu-virq timer0
NMI: 0 0 0 0 0 0 0 0 Nicht maskierbare Interrupts
LOC: 0 0 0 0 0 0 0 0 Lokale Timer-Interrupts
SPU: 0 0 0 0 0 0 0 0 Falsche Interrupts
PMI: 0 0 0 0 0 0 0 0 Leistungsüberwachungs-Interrupts
IWI: 0 0 0 0 0 0 0 0 0 IRQ-Arbeitsunterbrechungen
RES: 3607120 3551629 3422476 3802992 3482146 3468144 5374762 3236015 Interrupts neu planen
CAL: 770084 489287 952799 544546 919884 343765 863201 373596 Funktionsaufruf-Interrupts
TLB: 0 0 0 0 0 0 0 0 TLB-Abschüsse
TRM: 0 0 0 0 0 0 0 0 Thermische Ereignisunterbrechungen
THR: 0 0 0 0 0 0 0 0 Schwellenwert-APIC-Interrupts
MCE: 0 0 0 0 0 0 0 0 Maschinenprüfungsausnahmen
MCP: 0 0 0 0 0 0 0 0 Maschinenprüfungen
ERR: 0
MIS: 0
Alexander Gladysh
quelle
Bonusfrage: Gibt es eine Möglichkeit, die Anzahl der Interrupts zu verringern eth1?
Alexander Gladysh

Antworten:

10

Schauen Sie in das /proc/irq/283Verzeichnis. Es gibt eine smp_affinity_listDatei, die zeigt, welche CPUs den 283-Interrupt erhalten. Für Sie enthält diese Datei wahrscheinlich "0" (und smp_affinitywahrscheinlich "1").

Sie können den CPU-Bereich in die smp_affinity_listDatei schreiben :

echo 0-7 | sudo tee /proc/irq/283/smp_affinity_list

Oder Sie können eine Bitmaske schreiben, wobei jedes Bit einer CPU entspricht, um smp_affinity:

printf %x $((2**8-1)) | sudo tee /proc/irq/283/smp_affinity

Allerdings irqbalance ist bekannt , seine eigene Vorstellung von dem, was jede Affinität Interrupt haben sollte, und es könnte Ihren Updates zurück. Daher ist es am besten, wenn Sie irqbalance nur vollständig deinstallieren. Oder stoppen Sie es zumindest und deaktivieren Sie es beim Neustart.

Wenn Sie auch ohne Ungleichgewicht smp_affinitynach einem Neustart für Interrupt 283 ungerade werden , müssen Sie die CPU-Affinität in einem Ihrer Startskripte manuell aktualisieren.

Chutz
quelle
irqbalanceläuft schon. Vielleicht ist es nicht richtig konfiguriert? Wie überprüfe ich das?
Alexander Gladysh
Vielleicht sollten Sie einfach das Ungleichgewicht deaktivieren, neu starten und prüfen, ob dies hilft. Die Interrupts sind standardmäßig ziemlich gut ausgeglichen.
Chutz
Zu Ihrer Information: /proc/irq/283/smp_affinityhat 01jetzt drin (niemand hat das Zeug auf dieser Maschine nach meinem besten Wissen geändert - also muss dies die Systemvorgabe sein).
Alexander Gladysh
Entschuldigung, ich habe meine Antwort aktualisiert. Ungleichgewicht ist wahrscheinlich der Schuldige. Lass es einfach los. Ich weiß nicht, wie die Standardeinstellung lauten soll, aber aus Erfahrung habe ich gesehen, dass die Standardeinstellung "ALLE CPUs" ist.
Chutz
Das Deaktivieren irqbalance(via ENABLED=0in /etc/default/irqbalance) hilft nicht. Nach dem Neustart irqbalanceist stop/waiting, ist aber /proc/irq/283/smp_affinitynoch 01.
Alexander Gladysh
2

Wenn Sie das richtige Intel NIC-Modell haben, können Sie die Leistung erheblich verbessern.

Um den ersten Absatz zu zitieren:

Mit Multicore-Prozessoren und den neuesten Ethernet-Adaptern (einschließlich 82575, 82576, 82598 und 82599) können TCP-Weiterleitungsflüsse optimiert werden, indem einzelnen Kernen Ausführungsflüsse zugewiesen werden. Standardmäßig weist Linux Prozessorkernen automatisch Interrupts zu. Derzeit gibt es zwei Methoden zum automatischen Zuweisen der Interrupts: einen Inkernel-IRQ-Balancer und den IRQ-Balance-Daemon im Benutzerbereich. Beide bieten Kompromisse, die die CPU-Auslastung verringern, aber die IP-Weiterleitungsraten nicht maximieren. Ein optimaler Durchsatz kann erzielt werden, indem die Warteschlangen des Ethernet-Adapters manuell an bestimmte Prozessorkerne angeheftet werden.

Für die IP-Weiterleitung sollte ein Sende- / Empfangswarteschlangenpaar denselben Prozessorkern verwenden und die Cache-Synchronisation zwischen verschiedenen Kernen reduzieren. Dies kann durchgeführt werden, indem bestimmten Kernen Sende- und Empfangsinterrupts zugewiesen werden. Ab Linux-Kernel 2.6.27 können auf den 82575, 82576, 82598 und 82599 mehrere Warteschlangen verwendet werden. Außerdem wurden in MSI-X (Extended Messaging Signaled Interrupts) mehrere Übertragungswarteschlangen aktiviert. MSI-X unterstützt eine größere Anzahl von Interrupts, die verwendet werden können, wodurch eine feinere Steuerung und Ausrichtung der Interrupts auf bestimmte CPUs ermöglicht wird.

Siehe: Zuweisen von Interrupts zu Prozessorkernen mithilfe eines Intel® 82575/82576- oder 82598/82599-Ethernet-Controllers

Matt
quelle
2

Tatsächlich wird empfohlen, insbesondere bei sich wiederholenden Prozessen über einen kurzen Zeitraum, dass alle von einer Gerätewarteschlange generierten Unterbrechungen von derselben CPU anstatt von IRQ-Balancing behandelt werden. Daher wird eine bessere Leistung erzielt, wenn eine einzelne CPU den eth1-Interrupt behandelt *** Ausnahme unten angegeben

Die oben verlinkte Quelle stammt aus dem Linux-Symposium, und ich empfehle Ihnen, die paar Absätze zu SMP IRQ Affinity durchzulesen, da sie Sie effektiver überzeugen als dieser Beitrag.

Warum?

Denken Sie daran, dass jeder Prozessor seinen eigenen Cache hat, abgesehen davon, dass er auf den Hauptspeicher zugreifen kann. Schauen Sie sich dieses Diagramm an . Wenn ein Interrupt ausgelöst wird, muss ein CPU-Kern die Anweisungen abrufen, um den Interrupt aus dem Hauptspeicher zu behandeln. Dies dauert viel länger, als wenn sich die Anweisungen im Cache befinden. Sobald ein Prozessor eine Aufgabe ausgeführt hat, befinden sich diese Anweisungen im Cache. Angenommen, derselbe CPU-Kern verarbeitet fast immer denselben Interrupt. Die Interrupt-Handler-Funktion verlässt den CPU-Kern-Cache wahrscheinlich nicht und erhöht die Kernel-Leistung.

Wenn IRQ ausgeglichen ist, kann es alternativ die Unterbrechung so zuweisen, dass sie ständig von einer anderen CPU behandelt wird. Dann hat der neue CPU-Kern wahrscheinlich nicht die Interrupt-Handler-Funktion im Cache, und es wird eine lange Zeit erforderlich sein, um den richtigen Handler von main zu erhalten Erinnerung.

Ausnahme : Wenn Sie eth1-Interrupt selten verwenden, was bedeutet, dass genügend Zeit vergeht, dass der Cache durch andere Aufgaben überschrieben wird, was bedeutet, dass Daten zeitweise mit langen Zeiträumen dazwischen über diese Schnittstelle kommen ... dann werden Sie diese Vorteile höchstwahrscheinlich nicht sehen denn sie sind, wenn Sie einen Prozess mit hoher Frequenz verwenden.

Fazit

Wenn Ihr Interrupt sehr häufig auftritt, binden Sie diesen Interrupt nur an eine bestimmte CPU. Diese Konfiguration lebt bei

 /proc/'IRQ number'/smp_affinity

oder

/proc/irq/'IRQ number'/smp_affinity

Siehe den letzten Absatz in der SMP IRQ-Affinität Abschnitt aus der oben verlinkten Quelle, der Anweisungen enthält.

Alternative

Sie können die Häufigkeit ändern, mit der das Interrupt-Flag ausgelöst wird, indem Sie entweder die MTU-Größe (Jumbo-Frames) erhöhen, wenn das Netzwerk dies zulässt, oder das Flag ändern, nachdem eine größere Anzahl von Paketen empfangen wurde, anstatt bei jedem Paket ODER die Auszeit, also Interrupt nach einer bestimmten Zeit auslösen. Vorsicht bei der Zeitoption, da Ihre Puffergröße möglicherweise voll ist, bevor die Zeit abläuft. Dies kann mit dem in der verknüpften Quelle beschriebenen ethtool erfolgen .

Diese Antwort nähert sich der Länge, in der die Leute sie nicht lesen, so dass ich nicht ins Detail gehen werde, aber abhängig von Ihrer Situation gibt es viele Lösungen ... überprüfen Sie die Quelle :)

Bruder-Bilo
quelle