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.c
linux/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
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(¶virt_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, 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, 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)。
In both cases, steal time is reported from the hypervisor to the guest. In some cloud environments, this is accurately reported. In other cloud environments, it is not.
— Matthew S. Wilson (@_msw_) March 6, 2020
Hah, that's an oldie. As you can see, it was an extremely infrequent request (doesn't look like that has changed).
— Paul R. Nash (@paulrnash) March 6, 2020
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.
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