[LINUX] Erste Schritte mit der CPU-Diebstahlzeit

Es scheint viele Missverständnisse über die CPU-Diebstahlzeit zu geben. Beispielsweise ist es eine Metrik, die die Menge an CPU-Ressourcen anzeigt, die andere VMs auf demselben Host gestohlen haben, oder eine Metrik, die anzeigt, dass ein CPU-Ressourcenkonflikt vorliegt. Es ist wahr, dass die virtuelle Umgebung dazu neigt, die CPU-Ressourcen abhängig von den Einstellungen usw. zu ordnen, aber es ist nicht einfach zu schließen, dass sie "gestohlen" wurde, wenn man nur die CPU-Diebstahlzeit betrachtet.

Die CPU-Diebstahlzeit ist eine Metrik, die den Betrag zählt, den eine virtuelle Maschine über ihre zugewiesenen CPU-Ressourcen hinaus ausführen möchte. Ursprünglich ist es eine Metrik, die anstelle des Namens Steal Time als ** unfreiwillige Wartezeit ** bezeichnet werden sollte, wie im Kommentar in kernel / sched / cputime.c.

/proc/stat Lassen Sie uns zunächst überprüfen, woher die Steal-Time-Metrik "% st" stammt, die in "top (1)" und "vmstat (8)" zu sehen ist. Tatsächlich erhält diese Metrik nur Informationen von / proc / stat und berechnet sie. Ist es der folgende Teil?

fs/proc/stat.clinux/stat.c at master · torvalds/linux · GitHub:

		steal		+= cpustat[CPUTIME_STEAL];

Es scheint, dass ich gerade den Wert von "cpustat [CPUTIME_STEAL]" bekommen habe. Wo wird "cpustat [CPUTIME_STEAL]" ausgewiesen? Als ich es überprüfte, stieß ich auf die folgende Quelle

VM-CPU-Zeit

Berechnet in kernel / sched / cputime.c. Auszug.

linux/cputime.c at master · torvalds/linux · GitHub:

/*
 * Account for involuntary wait time.
 * @cputime: the CPU time spent in involuntary wait
 */

void account_steal_time(u64 cputime)
{
	u64 *cpustat = kcpustat_this_cpu->cpustat;
	cpustat[CPUTIME_STEAL] += cputime;
}
...
/*
 * When a guest is interrupted for a longer amount of time, missed clock
 * ticks are not redelivered later. Due to that, this function may on
 * occasion account more time than the calling functions think elapsed.
 */
static __always_inline u64 steal_account_process_time(u64 maxtime)
{
#ifdef CONFIG_PARAVIRT
	if (static_key_false(&paravirt_steal_enabled)) {
		u64 steal;

		steal = paravirt_steal_clock(smp_processor_id());
		steal -= this_rq()->prev_steal_time;
		steal = min(steal, maxtime);
		account_steal_time(steal);
		this_rq()->prev_steal_time += steal;

		return steal;
	}
#endif
	return 0;
}

Sie können sehen, dass account_steal_time () nur die gemessene Diebstahlzeit enthält. Es scheint, dass die tatsächliche Werterfassung durch "paravirt_steal_clock ()" erfolgt, das in "stehlen_account_process_time ()" aufgerufen wird.

Beachten Sie, dass Sie sich keine Sorgen machen müssen, wenn sowohl Xen als auch KVM als Gast-VMs ausgeführt werden, da diese normalerweise "CONFIG_PARAVIRT = y" haben und unabhängig von HVM / PV in "#ifdef CONFIG_PARAVIRT" gehen. Dies scheint ziemlich natürlich zu sein, da HVM häufig keine paravirtuellen Funktionen verwendet. Übrigens ist "CONFIG_PARAVIRT = y" genau eine Option, die nur den Paravirtualisierungscode mit oder ohne Virtualisierung aktiviert. Die Hilfeinhalte von Kconfig sind unten aufgeführt. linux/Kconfig at master · torvalds/linux · GitHub:

config PARAVIRT
	bool "Enable paravirtualization code"
	---help---
	  This changes the kernel so it can modify itself when it is run
	  under a hypervisor, potentially improving performance significantly
	  over full virtualization.  However, when run without a hypervisor
	  the kernel is theoretically slower and slightly larger.

Nun, die Geschichte ist aus, aber es war "paravirt_steal_clock ()", das tatsächlich die Diebstahlzeit zählte. Wenn Sie dies befolgen, [linux / paravirt.h at master · torvalds / linux · GitHub](https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/paravirt.h# Sie können sehen, dass es in L34-L37 als "pv_ops.time.steal_clock" abstrahiert ist. Unten ist dieser Teil:

static inline u64 paravirt_steal_clock(int cpu)
{
	return PVOP_CALL1(u64, time.steal_clock, cpu);
}

Da es ein Makro gibt, können Sie durch etwas verwirrt sein, aber wenn Sie dieses Makro erweitern, erhalten Sie "pv_ops.time.steal_clock" von "time.steal_clock". Mit anderen Worten, Sie können sehen, dass die ursprüngliche Identität "pv_ops.time.steal_clock" ist.

Schauen wir uns nun an, was für Xen und KVM als "pv_ops.time.steal_clock" registriert ist.

Für Xen

Für Xen ist es in "drivers / xen / time.c" definiert.

linux/time.c at master · torvalds/linux · GitHub:

	pv_ops.time.steal_clock = xen_steal_clock;

Die Realität ist:

u64 xen_steal_clock(int cpu)
{
	struct vcpu_runstate_info state;

	xen_get_runstate_snapshot_cpu(&state, cpu);
	return state.time[RUNSTATE_runnable] + state.time[RUNSTATE_offline];
}

Anscheinend scheint es im Fall von Xen die Diebstahlzeit aus dem Zustand der VCPU zu messen. Beachten Sie, dass xen_get_runstate_snapshot_cpu () einen Snapshot des VCPU-Status zu diesem Zeitpunkt erstellt. Diese Funktion ist auch in derselben Quelldatei definiert. Wenn Sie also interessiert sind, lesen Sie dies bitte. Die Bedeutungen von "RUNSTATE_runnable" und "RUNSTATE_offline" finden Sie in "include / xen / interface / vcpu.h".

linux/vcpu.h at master · torvalds/linux · GitHub:

/* VCPU is currently running on a physical CPU. */
#define RUNSTATE_running  0

/* VCPU is runnable, but not currently scheduled on any physical CPU. */
#define RUNSTATE_runnable 1

/* VCPU is blocked (a.k.a. idle). It is therefore not runnable. */
#define RUNSTATE_blocked  2

/*
 * VCPU is not runnable, but it is not blocked.
 * This is a 'catch all' state for things like hotplug and pauses by the
 * system administrator (or for critical sections in the hypervisor).
 * RUNSTATE_blocked dominates this state (it is the preferred state).
 */
#define RUNSTATE_offline  3

Wie Sie oben sehen können, spiegeln RUNSTATE_runnable und RUNSTATE_offline nicht die Auswirkungen anderer Ressourcen wider. Wenn der auf der virtuellen Maschine ausgeführten Anwendung die erforderlichen Ressourcen zugewiesen sind, befindet sich die VCPU nicht im Status "Ausführbar". Es kann "laufen", "blockiert" oder "offline" sein. Xen kann zusätzliche Ressourcen ausleihen, aber keine Ressourcen von anderen VMs stehlen. Wenn sich die VCPU einer virtuellen Maschine für eine lange Zeit im Status "Ausführbar" befindet und die Diebstahlzeit von "top" / "vmstat" hoch ist, bedeutet dies, dass die virtuelle Maschine mehr CPU-Ressourcen anfordert, als sie verwenden kann. .. Wenn Steal TIme plötzlich aufspringt, ist möglicherweise etwas schief gelaufen.

Für KVM

Bei KVM ist der Steal-Wert direkt aus dem MSR zu lesen. Die Definition finden Sie in arch / x86 / kernel / kvm.c.

linux/kvm.c at master · torvalds/linux · GitHub:

static void __init kvm_guest_init(void)

{
	int i;
	paravirt_ops_setup();
...
	if (kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
		has_steal_clock = 1;
		pv_ops.time.steal_clock = kvm_steal_clock;
	}

linux/kvm.c at master · torvalds/linux · GitHub:

static u64 kvm_steal_clock(int cpu)
{
	u64 steal;
	struct kvm_steal_time *src;
	int version;

	src = &per_cpu(steal_time, cpu);
	do {
		version = src->version;
		virt_rmb();
		steal = src->steal;
		virt_rmb();
	} while ((version & 1) || (version != src->version));

	return steal;
}

Es wird nur das MSR (Model Specific Register) geladen. Wahrscheinlich ist die Implementierung des bereitgestellten Werts linux / x86.c at master · torvalds / linux · GitHub. Es wird der Teil von x86.c # L2651-L2694) sein, aber ich habe es hier nicht befolgt. Glücklicherweise wird diese Definition in der Dokumentation erwähnt.

https://www.kernel.org/doc/Documentation/virtual/kvm/msr.txt

MSR_KVM_STEAL_TIME: 0x4b564d03 ... steal: the amount of time in which this vCPU did not run, in nanoseconds. Time during which the vcpu is idle, will not be reported as steal time.

Es wird als die Zeit geschrieben, zu der die VCPU nur im Leerlauf ausgeführt wurde. Ähnlich wie Xen.

Beachten Sie, dass die Steal-Zeit vom Hypervisor sowohl in Xen als auch in KVM bereitgestellt wird, wie wir oben gesehen haben. Abhängig vom Cloud-Dienstanbieter scheint es jedoch einen Unterschied zu geben, ob dieser Wert je nach Umgebung korrekt angegeben wird oder nicht. Es scheint, dass GCE keine Diebstahlszeit gemeldet hat. VP bei AWS/Ein angesehener Ingenieur seinMatthew S. Wilson(@msw)Herr.| TwitterVia,ichwarzuvorProductDirectorvonGCEbeiGooglePaulR.Nash(@paulrnash)Herr.|TwitterBrachtemirbei(IchbinjetztinMSAzure)。

Ich habe gehört, dass GCE einen KVM-basierten Hypervisor verwendet. Ist "MSR_KVM_STEAL_TIME" also nicht aktiviert? Ich kenne die Details nicht.

Zusammenfassung

Im Allgemeinen weist die Situation, in der die CPU-Diebstahlzeit gezählt wird, nicht auf ein Problem mit dem zugrunde liegenden Host hin. Die Diebstahlzeit deckt auch die Zeit ab, die für Hypervisoren und VMMs aufgewendet wird, die im Auftrag von Gästen arbeiten, und erfordert im Grunde mehr als die Toleranz, die der VM für die Ausführung eingeräumt wird. Es zeigt die Zeit der Minute.

Sie sollten die Gast- und Hostmetriken sorgfältig prüfen und die entsprechende VM auswählen. Die CPU-Diebstahlzeit ist eine Art Indikator für die Auswahl der richtigen virtuellen Maschine. Bei der Betrachtung des für die Ausführung einer Aufgabe erforderlichen CPU-Verbrauchs ist es wichtig, die Wartezeit für die Ausführung der physischen CPU abziehen zu können. Die CPU-Diebstahlzeit kann dabei helfen.

Wenn sich die CPU-Diebstahlzeit erhöht, lesen Sie zuerst die Dokumentation für Ihre virtuelle Umgebung, analysieren Sie die vom Host bereitgestellten Metriken und prüfen Sie, ob sie gültig sind.

Recommended Posts

Erste Schritte mit der CPU-Diebstahlzeit
Erste Schritte mit Android!
1.1 Erste Schritte mit Python
Erste Schritte mit apache2
Erste Schritte mit Python
Erste Schritte mit Django 1
Einführung in die Optimierung
Erste Schritte mit Spark
Erste Schritte mit Python
Erste Schritte mit Pydantic
Erste Schritte mit Jython
Erste Schritte mit Django 2
Übersetzen Erste Schritte mit TensorFlow
Einführung in Python-Funktionen
Einführung in Tkinter 2: Button
Erste Schritte mit PKI mit Golang ―― 4
Erste Schritte mit Python Django (1)
Erste Schritte mit Python Django (3)
Einführung in Python Django (6)
Erste Schritte mit Django mit PyCharm
Erste Schritte mit Python Responder v2
Einführung in Git (1) History-Speicher
Erste Schritte mit Sphinx. Generieren Sie Docstring mit Sphinx
Erste Schritte mit Python-Webanwendungen
Erste Schritte mit Python für PHPer-Klassen
Erste Schritte mit Sparse Matrix mit scipy.sparse
Erste Schritte mit Julia für Pythonista
Erste Schritte mit Python Grundlagen von Python
Erste Schritte mit der Cisco Spark REST-API
Erste Schritte mit genetischen Python-Algorithmen
Erste Schritte mit Python 3.8 unter Windows
Erste Schritte mit Python für PHPer-Funktionen
Erste Schritte mit Python3 # 1 Grundkenntnisse erlernen
Erste Schritte mit Python Web Scraping Practice
Erste Schritte mit Python für PHPer-Super Basics
Erste Schritte mit Python Web Scraping Practice
Erste Schritte mit Dynamo von Python Boto
Erste Schritte mit Lisp für Pythonista: Ergänzung
Erste Schritte mit Heroku, Bereitstellen der Flaschen-App
Erste Schritte mit TDD mit Cyber-dojo bei MobPro
Erste Schritte mit Python mit 100 Klopfen bei der Sprachverarbeitung
MongoDB-Grundlagen: Erste Schritte mit CRUD mit JAVA
Erste Schritte mit dem Zeichnen mit matplotlib: Schreiben einfacher Funktionen
Erste Schritte mit der japanischen Übersetzung des Keras Sequential-Modells
[Übersetzung] Erste Schritte mit Rust für Python-Programmierer
Django Erste Schritte Teil 2 mit dem Eclipse Plugin (PyDev)
Erste Schritte mit AWS IoT in Python
Erste Schritte mit Pythons Ast-Modul (Verwenden von NodeVisitor)
Materialien zum Lesen, wenn Sie mit Python beginnen
Einstellungen für den Einstieg in MongoDB mit Python
Django 1.11 wurde mit Python3.6 gestartet
Erste Schritte mit Python3 # 2 Erfahren Sie mehr über Typen und Variablen
Erste Schritte mit Pandas: Grundkenntnisse, an die Sie sich zuerst erinnern sollten
Erste Schritte mit Google App Engine für Python und PHP
Einführung in die Tensorflow-About-Hypothese und die Kosten der linearen Regression