[LINUX] Premiers pas avec CPU Steal Time

Il semble y avoir beaucoup de malentendus sur le CPU Steal Time. Par exemple, il s'agit d'une métrique qui indique la quantité de ressources CPU que d'autres machines virtuelles exécutées sur le même hôte ont volé les ressources CPU qui devraient leur être allouées, ou une métrique qui indique qu'un conflit de ressources CPU se produit. Il est vrai que l'environnement virtuel a tendance à surallouer les ressources du processeur en fonction des paramètres, etc., mais il n'est pas possible de conclure simplement qu'il a été "volé" simplement en regardant le CPU Steal Time.

CPU Steal Time est une métrique qui compte la quantité qu'une machine virtuelle tente d'exécuter au-delà de ses ressources CPU allouées. À l'origine, c'est une métrique qui devrait être appelée ** temps d'attente involontaire ** au lieu du nom Steal Time, comme dans le commentaire dans kernel / sched / cputime.c.

/proc/stat Tout d'abord, vérifions d'où viennent les métriques de temps de vol % st, qui peuvent être vues dans top (1) ʻet vmstat (8). En fait, cette métrique n'obtient des informations que de / proc / stat` et les calcule. Est-ce la partie suivante?

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

		steal		+= cpustat[CPUTIME_STEAL];

Il semble que je viens d'avoir la valeur de cpustat [CPUTIME_STEAL]. Alors, où cpustat [CPUTIME_STEAL] est-il pris en compte? Quand je l'ai vérifié, je suis tombé sur la source suivante

Temps CPU de la VM

Calculé dans kernel / sched / cputime.c. Extrait.

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;
}

Vous pouvez voir que ʻaccount_steal_time () contient uniquement le temps de vol mesuré. Il semble que l'acquisition de la valeur réelle se fasse par paravirt_steal_clock (), qui est appelée dans steal_account_process_time ()`.

Notez que si vous exécutez à la fois Xen et KVM en tant que VM invitées, vous avez généralement CONFIG_PARAVIRT = y quel que soit HVM / PV, et vous n'avez pas à vous inquiéter car il sera dans #ifdef CONFIG_PARAVIRT. Cela semble plutôt naturel, car HVM n'utilise souvent pas les fonctionnalités paravirtuelles. D'ailleurs, CONFIG_PARAVIRT = y est exactement une option qui n'active que le code de paravirtualisation, avec ou sans virtualisation. Le contenu de l'aide de Kconfig est extrait ci-dessous. 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.

Eh bien, l'histoire est fausse, mais c'est paravirt_steal_clock () qui a en fait compté le temps de vol. Si vous suivez ceci, [linux / paravirt.h sur master · torvalds / linux · GitHub](https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/paravirt.h# Vous pouvez voir qu'il est abstrait comme pv_ops.time.steal_clock dans L34-L37). Ci-dessous cette partie:

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

Puisqu'il y a une macro, vous pouvez être confus par quelque chose, mais si vous développez cette macro, vous obtiendrez pv_ops.time.steal_clock de time.steal_clock. En d'autres termes, vous pouvez voir que l'identité d'origine est pv_ops.time.steal_clock.

Regardons maintenant ce qui est enregistré comme pv_ops.time.steal_clock pour Xen et KVM, respectivement.

Pour Xen

Pour Xen, il est défini dans drivers / xen / time.c.

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

	pv_ops.time.steal_clock = xen_steal_clock;

La réalité est:

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];
}

Apparemment, dans le cas de Xen, il semble mesurer le temps de vol de l'état du VCPU. Notez que xen_get_runstate_snapshot_cpu () prend un instantané de l'état du VCPU à ce moment-là. Cette fonction est également définie dans le même fichier source, donc si vous êtes intéressé, veuillez le voir. Les significations de RUNSTATE_runnable et RUNSTATE_offline sont décrites dans ʻ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

Comme vous pouvez le voir sur ce qui précède, RUNSTATE_runnable et RUNSTATE_offline ne reflètent pas les effets des autres ressources prises. Si l'application exécutée sur la machine virtuelle dispose des ressources nécessaires allouées, le VCPU ne sera pas dans l'état exécutable. Cela peut être «en cours», «bloqué» ou «hors ligne». Xen peut emprunter des ressources supplémentaires, mais il ne peut pas voler les ressources d'autres machines virtuelles. Si le VCPU d'une machine virtuelle est dans l'état «exécutable» pendant une longue période et que le temps de vol de «top» / «vmstat» est élevé, cela signifie que la machine virtuelle demande plus de ressources CPU qu'elle ne peut en utiliser. .. Au lieu de cela, si Steal TIme saute soudainement, il est possible que quelque chose se soit mal passé.

Pour KVM

Pour KVM, la valeur de vol doit être lue directement à partir du MSR. Vous pouvez trouver la définition dans ʻ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;
}

Il charge simplement le MSR (Model Specific Register). L'implémentation de la valeur fournie est probablement [linux / x86.c at master · torvalds / linux · GitHub](https://github.com/torvalds/linux/blob/master/arch/x86/kvm/ Ce sera la partie de x86.c # L2651-L2694), mais je ne l'ai pas suivi ici. Heureusement, la documentation mentionne cette définition.

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.

Il est écrit comme l'heure à laquelle le VCPU n'a pas été exécuté sauf inactif. Similaire à Xen.

Notez que le temps de vol est fourni par l'hyperviseur à la fois dans Xen et KVM, comme nous l'avons vu ci-dessus. Cependant, selon le fournisseur de services cloud, il semble qu'il y ait une différence dans la fourniture correcte ou non de cette valeur en fonction de l'environnement. Il semble que GCE n'a pas signalé de vol de temps. VP sur AWS/Être un ingénieur distinguéMatthew S. Wilson(@msw)M.| TwitterVia,j'étaisauparavantdirecteurproduitdeGCEsurgooglePaulR.Nash(@paulrnash)M.|TwitterM'aappris(JesembleêtredansMSAzuremaintenant)。

J'ai entendu dire que GCE utilise un hyperviseur basé sur KVM, donc «MSR_KVM_STEAL_TIME» n'est-il pas activé? Je ne connais pas les détails.

Résumé

En général, la situation où le temps de vol du processeur est compté n'indique pas un problème avec l'hôte sous-jacent. Le temps de vol couvre également le temps passé sur les hyperviseurs et les VMM fonctionnant pour le compte des invités, et nécessite essentiellement plus que la valeur autorisée donnée à la machine virtuelle pour s'exécuter. Il révèle l'heure de la minute.

Vous devez vérifier attentivement les métriques d'invité et d'hôte et sélectionner la VM appropriée. Le temps de vol du processeur est une sorte d'indicateur pour choisir la bonne machine virtuelle. Lorsque vous examinez la consommation de CPU requise pour effectuer une tâche, il est important de pouvoir soustraire le temps d'attente de la CPU physique pour s'exécuter. Le temps de vol du processeur peut aider pour cela.

Lorsque le temps de vol du processeur augmente, lisez d'abord la documentation de votre environnement virtuel, analysez les métriques fournies par l'hôte et voyez si elles sont valides.

Recommended Posts

Premiers pas avec CPU Steal Time
Premiers pas avec Android!
1.1 Premiers pas avec Python
Premiers pas avec apache2
Premiers pas avec Python
Premiers pas avec Django 1
Introduction à l'optimisation
Premiers pas avec Spark
Premiers pas avec Python
Premiers pas avec Pydantic
Premiers pas avec Jython
Premiers pas avec Django 2
Traduire Premiers pas avec TensorFlow
Introduction aux fonctions Python
Introduction à Tkinter 2: Button
Premiers pas avec PKI avec Golang ―― 4
Premiers pas avec Python Django (1)
Premiers pas avec Python Django (3)
Introduction à Python Django (6)
Premiers pas avec Django avec PyCharm
Premiers pas avec Python responder v2
Introduction à Git (1) Stockage d'historique
Premiers pas avec Sphinx. Générer docstring avec Sphinx
Premiers pas avec les applications Web Python
Premiers pas avec Python pour les classes PHPer
Premiers pas avec Sparse Matrix avec scipy.sparse
Premiers pas avec Julia pour Pythonista
Premiers pas avec Python Bases de Python
Premiers pas avec Cisco Spark REST-API
Premiers pas avec les algorithmes génétiques Python
Premiers pas avec Python 3.8 sous Windows
Premiers pas avec Python pour les fonctions PHPer
Premiers pas avec python3 # 1 Apprenez les connaissances de base
Premiers pas avec Python Web Scraping Practice
Premiers pas avec Python pour PHPer-Super Basics
Premiers pas avec Python Web Scraping Practice
Premiers pas avec Dynamo de Python boto
Premiers pas avec Lisp pour Pythonista: Supplément
Premiers pas avec Heroku, déploiement de l'application Flask
Premiers pas avec TDD avec Cyber-dojo chez MobPro
Démarrer avec Python avec 100 coups sur le traitement du langage
Principes de base de MongoDB: Premiers pas avec CRUD avec JAVA
Premiers pas avec le dessin avec matplotlib: écrire des fonctions simples
Premiers pas avec la traduction japonaise du modèle séquentiel Keras
[Français] Premiers pas avec Rust pour les programmeurs Python
Django Getting Started Part 2 avec eclipse Plugin (PyDev)
Premiers pas avec AWS IoT facilement en Python
Premiers pas avec le module ast de Python (à l'aide de NodeVisitor)
Matériel à lire lors de la mise en route de Python
Paramètres pour démarrer avec MongoDB avec python
Django 1.11 a démarré avec Python3.6
Premiers pas avec python3 # 2 En savoir plus sur les types et les variables
Premiers pas avec les pandas: connaissances de base à retenir en premier
Premiers pas avec Google App Engine pour Python et PHP
Introduction à l'hypothèse Tensorflow-About et au coût de la régression linéaire