Dies ist keine Antwort auf genau Ihre Frage. Wie auch immer, @Klas weist darauf hin
Ein unfreiwilliger Kontextwechsel tritt auf, wenn ein Thread zu lange läuft
Meine Idee ist also, dass Sie überprüfen können, was Ihre Threads zu lange laufen. Verwenden Sie perf und finden Sie Stellen in Ihrem Code, an denen die Kontextwechsel am häufigsten vorkommen. Und vergleichen Sie ggf. die Messwerte der alten Version Ihres Programms mit der neuen.
Perf (https://perf.wiki.kernel.org/index.php/Tutorial) hat das Ereignis context-switches
. Sie können es messen und Stacktraces sammeln, wo es passiert. Dies ist ein Beispiel für die Messung von Kontextwechseln:
perf record -e cs -g -p `pidof my_test` sleep 5
Und dann prüfen, wo sie passieren. Beispielsweise gibt es in C++ ein Programm mit einer Endlosschleife ohne jegliche Systemaufrufe. Alle Schalterinhalte haben stracetrace von meiner Funktion my_thread_func
:
perf report --stdio -g --kallsym=/boot/System.map-2.6.32-431.el6.x86_64
# Samples: 7 of event 'cs'
# Event count (approx.): 7
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. .............................
#
100.00% my_test [kernel.kallsyms] [k] perf_event_task_sched_out
|
--- perf_event_task_sched_out
schedule
retint_careful
my_thread_func(void*)
Im Gegenteil, dies ist ein Maß für ein Programm in C++, das eine Endlosschleife mit vielen Systemaufrufen hat:
# Samples: 6 of event 'cs'
# Event count (approx.): 6
#
# Overhead Command Shared Object Symbol
# ........ ............... ................. .............................
#
100.00% my_test_syscall [kernel.kallsyms] [k] perf_event_task_sched_out
|
--- perf_event_task_sched_out
schedule
|
|--83.33%-- sysret_careful
| syscall
|
--16.67%-- retint_careful
syscall
Ein freiwilliger Kontextwechsel kann immer dann erfolgen, wenn ein Thread/Prozess einen blockierenden Systemaufruf durchführt.
Ein unfreiwilliger Kontextwechsel tritt auf, wenn ein Thread zu lange gelaufen ist (normalerweise etwa 10 ms), ohne dass ein Systemaufruf erfolgt, der blockiert, und Prozesse auf die CPU warten.
Es sieht so aus, als ob Ihr Programm jetzt CPU-intensiver ist als zuvor. Wenn Sie es multi-threaded gemacht haben, ist wahrscheinlich eine Steigerung zu erwarten.
821 Kontextwechsel - abhängig von der Ausführungszeit Ihres Programms kann dies eine Menge sein oder auch nicht.
Wenn Sie die Anzahl der Kontextwechsel reduzieren möchten, können Sie die Anzahl der Worker-Threads reduzieren, sodass weniger Threads als CPU-Kerne vorhanden sind.
Aktualisieren
Unter der Annahme, dass die Last in beiden Fällen identisch ist, sieht es so aus, als hätten die Codeänderungen die CPU-Auslastung erhöht. Wenn die erhöhte Last ein Problem darstellt, sollten Sie den Code analysieren, um den Engpass zu finden. Instrumentierung kann hilfreich sein, um zu isolieren, welcher Teil des Codes das Problem verursacht.