
Wir haben kürzlich eine hohe durchschnittliche Auslastung von etwa 1,5 auf unserem eingebetteten System festgestellt, obwohl (laut htop
) praktisch alle Prozesse schlafen sollten.
Das fragliche System ist ein Dual-Core Cortex-A9 mit einem Echtzeit-Linux-Kernel (4.14.126), der mit Buildroot erstellt wurde. Wir verwenden initramfs für unser Root-Dateisystem und es gibt keinen Swap, also gibt es definitivkein Festplatten-E/Awährend des Normalbetriebs.
Nach einigem Suchen fanden wir heraus, dass die Belastung durch ein Programm namensswupdate, das uns eine praktische Weboberfläche für Software-Updates bietet (und das wir sehr gerne auch weiterhin nutzen möchten).
Wenn ich time
die durchschnittliche CPU-Auslastung dieser Anwendung schätze (durch Berechnung(Benutzer+Sys)/Real), erhalte ich einen Wert von nur etwa 1 %, was angesichts der durchschnittlichen Auslastung von 1,5 nicht viel Sinn macht.
Ich weiß, dass die durchschnittliche Auslastung auch Prozesse in diesem TASK_UNINTERRUPTIBLE
Zustand umfasst, die nicht zur CPU-Auslastung beitragen. Was ich nicht verstehe, ist, warum sich einer der Threads/Prozesse dieser Anwendung jemals in diesem Zustand befinden sollte.
Um die Situation weiter zu analysieren, habe ich einen Kernel-Trace aufgezeichnet mitltng, was zeigt, dass swupdate nur Folgendes macht (alle 50 ms):
Wie Sie sehen können, gibt es ein wenig von dem, was wie Socket-basiertes IPC aussieht, und eine Auswahl wartet aufetwas. Im IPC-Fall scheint ein Thread größtenteils in zu blockieren nanosleep()
, während der andere in blockiert accept()
. Soweit ich weiß, sollte keiner von beiden Systemressourcen verbrauchen.
Zu Ihrer Information: Die Zeitbasis für beide Screenshots ist dieselbe, und der IPC dauert insgesamt ca. 500-600µs (was angesichts des Intervalls von 50ms ganz gut zur beobachteten CPU-Auslastung von 1% passt)
Was also verursacht hier die Belastung?
Antwort1
Da Tasks sowohl im Status R als auch im Status D zur Linux-Last beitragen, können Sie alle Threads in Ihrem System in einem dieser beiden Zustände abfragen. Beispiel:
for x in {1..100} ; do ps -aeos,user,comm,wchan | grep "^[RD]" ; sleep 0.1 ; done | sort | uniq -c | sort -nbr | head -20
Unten sehen Sie ein Beispiel für die Ausgabe. Sie müssen die oberste Zeile ignorieren, die Ihren eigenen ps
Prozess anzeigt, der immer aktiv ist, da dieser die gesamte Abtastung durchführt:
# for x in {1..100} ; do
> ps -aeos,user,comm,wchan | grep "^[RD]"
> sleep 0.1
> done | sort | uniq -c | sort -nbr | head -20
100 R root ps -
3 R oracle oracle_14047_li -
2 R root rcu_sched rcu_gp_kthread
2 R root rcu_sched -
2 R root kworker/1:2-eve -
2 R oracle perl -
2 R oracle ora_vktm_lin19c hrtimer_nanosleep
2 D root md10_raid10 md_super_wait
2 D oracle ora_ckpt_linprd md_write_start
1 R redis redis-server -
1 R oracle ora_vktm_linprd hrtimer_nanosleep
1 R oracle ora_m001_linprd -
1 D root xfsaild/dm-18 rq_qos_wait
1 D oracle ora_mz00_lin19c x64_sys_io_destroy
1 D oracle ora_lg00_lin19c inode_dio_wait
1 D oracle ora_dbrm_lin19c msleep
Sofern Sie keinen alten Kernel verwenden, sollten Sie dies als Root ausführen, da neuere Kernel die WCHAN-Werte der Prozesse anderer Benutzer maskieren.
Sie können noch tiefer gehen (aber nicht mit ps), Sie können Stichproben nehmen /proc/PID/syscall
und /proc/PID/stack
auch Systemaufruf- und Kernel-Stacktrace-Informationen abrufen. Ich habe psn
hierfür ein Tool namens Linux Process Snapper ( ) geschrieben, mit dem Sie ziemlich detaillierte Informationen zu solchen Leistungsproblemen erhalten können, ohne auf Kernel-Tracing zurückgreifen zu müssen:
[tanel@linux01 ~]$ sudo psn -G syscall,wchan
Linux Process Snapper v0.18 by Tanel Poder [https://0x.tools]
Sampling /proc/syscall, stat, wchan for 5 seconds... finished.
=== Active Threads ==========================================================================================
samples | avg_threads | comm | state | syscall | wchan
-------------------------------------------------------------------------------------------------------------
511 | 255.50 | (kworker/*:*) | Disk (Uninterruptible) | [kernel_thread] | blkdev_issue_flush
506 | 253.00 | (oracle_*_l) | Disk (Uninterruptible) | pread64 | do_blockdev_direct_IO
28 | 14.00 | (oracle_*_l) | Running (ON CPU) | [running] | 0
1 | 0.50 | (collectl) | Running (ON CPU) | [running] | 0
1 | 0.50 | (mysqld) | Running (ON CPU) | [running] | 0
1 | 0.50 | (ora_lgwr_lin*c) | Disk (Uninterruptible) | io_submit | inode_dio_wait
1 | 0.50 | (oracle_*_l) | Disk (Uninterruptible) | pread64 | 0
1 | 0.50 | (oracle_*_l) | Running (ON CPU) | [running] | SYSC_semtimedop
1 | 0.50 | (oracle_*_l) | Running (ON CPU) | [running] | read_events
1 | 0.50 | (oracle_*_l) | Running (ON CPU) | read | 0
1 | 0.50 | (oracle_*_l) | Running (ON CPU) | semtimedop | SYSC_semtimedop
Sie können noch viel tiefer gehen, einen entsprechenden Blogeintrag finden Sie hier:
Antwort2
CPU-Auslastung und -Last sind unterschiedliche Messwerte. Tatsächlich kann die Auslastung über 1 liegen. CPU ist die tatsächlich von der CPU genutzte Zeit, sie sollte also immer unter 100 % liegen (aber bei mehreren Kernen/CPUs, aber Sie verstehen schon). Die Auslastung gibt die Belastung an: wie viele Prozesse laufen und darauf warten, ausgeführt zu werden.
Wie Sie wahrscheinlich wissen (aus der Diskussion in Ihrer Frage), ist I/O normalerweise eine solche Wartezeit, sodass die Belastung zunimmt. Es kann aber auch Signale/Semaphoren/Sperren geben, die zu Wartezeiten führen können, und diese können nur durch einen Prozess verursacht werden, der keine I/O durchführt). Wenn beispielsweise jede Sekunde ein Prozess aktiviert wird und viele Prozesse auf Daten von diesem Prozess warten, ist die Belastung höher (entspricht der Anzahl der wartenden Prozesse).
Pipes werden Ihnen möglicherweise als E/A angezeigt, aber mmap und Sperren ... klassifizieren Sie sie als IO? Sie werden nicht in Bio (Block-E/A) angezeigt, daher werden sie Ihnen möglicherweise in vielen Ladestatistiken nicht angezeigt.
Dies lässt sich häufig am einfachsten herausfinden, indem man einen Prozess blockiert und prüft, wo er sich befindet. Wenn Sie dies mehrmals tun, werden Sie hoffentlich feststellen, dass eine Funktion blockiert (und Sie werden dies möglicherweise häufiger feststellen als andere Funktionen).
Antwort3
Ich hatte das gleiche Problem auf einem eingebetteten System, das auf einem i.mx28 mit etwa 450 MHz lief.
htop
zeigte ständig eine CPU-Auslastung von 50 % an, die ausschließlich durch eine der swupdate
Aufgaben verursacht wurde.
Beim Durchsuchen mongoose_interface.c
Ihrer 100-ms-Beobachtung, die beim Lesen am Ende von ausgelöst wurde start_mongoose()
:
mg_mgr_poll(&mgr, 100);
Ich habe experimentell 100 auf 1000 geändert und nach einer Neukompilierung und einem Neustart sank die CPU-Auslastung auf etwa 2 % der swupdate
Threads, wie in beobachtet htop
.
Wie gesagt, das war experimentell, da mir die Zahlen zu sehr nach Zufallszahlen vorkamen. Ob irgendwelche Nebenwirkungen auftreten, habe ich nicht untersucht.