Aujourd'hui, je vais parler des voyants rouges et verts clignotants et de la manière dont ils nous ont menés dans le cadre d'une longue enquête sur les performances qui s'est terminée profondément dans les pilotes PCI Express du noyau Linux.
(En outre, si vous ne l'avez pas déjà vu, consultez la deuxième partie de la série de blogs Road to All-Flash, par les gens qui ont construit la plate-forme dont je discute dans ce post.)
La ballade des lumières clignotantes.
Il y a environ un an, je travaillais sur notre nouveau Plateforme tout flash NVMe et un problème étrange est apparu.
En cas de défaillance d'un disque SSD, nous ne pouvions pas allumer le petit voyant rouge du lecteur pour indiquer celui qui devait être remplacé. En effet, un lecteur NVMe est connecté (plus ou moins) directement au processeur via PCI-Express, par opposition aux lecteurs SATA ou SAS, qui se connectent à un contrôleur distinct qui sait comment procéder, par exemple, allumer et éteindre les lumières.
Cela peut sembler anodin, mais un retour visuel dans le centre de données est important pour les administrateurs de stockage qui doivent remplacer le disque défectueux (et non le mauvais). Dans le meilleur des cas, le lecteur est tellement à plat que le voyant est éteint. Dans le pire des cas, l’administrateur de stockage est confronté à une mission périlleuse: un choix impossible. («Coupez le fil rouge!» «Quel fil rouge? Il y a vingt-quatre fils et ils sont tous verts!)
Heureusement, ce problème a une solution, et cette solution s'appelle Intel Volume Management Device (VMD). VMD est une fonctionnalité du complexe racine de certains processeurs Xeon qui peut agir en tant que délégué pour les événements NVMe, en les acheminant vers les pilotes logiciels. En plus de savoir comment allumer et éteindre les lumières, il prend également en charge un branchement à chaud plus fiable - win win!
Eh bien, pas tout à fait.
Les gars du PC de jeu avaient raison. LED do impact sur les performances.
Lorsque nous avons activé l'utilisation de VMD, les choses ont ralenti. UNE lot Ralentissez. Nos benchmarks de débit ont montré des régressions de 50% ou moins - l'une des charges de travail les plus touchées atteignait auparavant des vitesses d'environ 15 Go / s, mais avait maintenant du mal à atteindre 6 Go / s.
Au début, nous craignions que quelque chose dans le fonctionnement de VMD ne limite fondamentalement le débit que nous pourrions obtenir des disques SSD. VMD agit en quelque sorte comme un intermédiaire et l'un de ses effets consiste à créer un aliasing de plusieurs périphériques de stockage derrière un ensemble limité et partagé de vecteurs d'interruption. Sans VMD, chaque disque a ses propres vecteurs d’interruption qu’il n’a pas à partager. Nous soupçonnions que la controverse sur ces ressources d'interruption était ce qui nous ralentissait.
En fin de compte, nous étions presque droite.
Pendant que nous explorions nous-mêmes les données de performance, nous avons également contacté des spécialistes d'Intel pour nous aider à résoudre le problème. Leur aide s’est révélée précieuse pour identifier le véritable coupable de ce mystère.
Les moyennes peuvent être trompeuses et d'autres faits évidents
L'une des premières choses que nous avons examinées était la latence moyenne des demandes d'E / S pour les disques dans les deux configurations - VMD désactivé et VMD activé. À notre grande surprise, il n'y avait pas une si grande différence de latence moyenne. C'était sensiblement plus élevé avec VMD activé, mais seulement un peu. Des graphiques comme celui-ci (à partir de données capturées lors d'un test d'écriture) étaient typiques:
Des microsecondes 10-15 supplémentaires par demande ne sont pas géniales, mais elles ne suffisent pas pour expliquer les% de pertes de débit de 50-60, même si nous étions totalement liés à la latence.
Pendant ce temps, les ingénieurs d'Intel examinaient leur code de pilote. Il y avait quelques problèmes mineurs qu'ils connaissaient et avaient en fait déjà résolus dans les versions du noyau ultérieures à celle que nous utilisions, alors ils nous ont fourni des correctifs, nous avons construit un module de noyau personnalisé et nous sommes partis pour les courses - mais ces correctifs n'ont amélioré que légèrement les performances.
Ils ont trouvé un autre problème: le pilote VMD ne considérait pas correctement l'affinité CPU souhaitée des périphériques lors de l'attribution des vecteurs d'interruption. Le correctif pour résoudre ce problème a également ajouté une option de pilote - max_vec, qui régit le nombre maximum de vecteurs d'interruption que le VMD tentera d'allouer pour chaque périphérique connecté. La valeur par défaut était auparavant 4.
Un autre patch, un autre cycle de reconstruction du pilote et un autre ensemble de tests - et, à notre grande satisfaction, les performances étaient considérablement meilleures. Mais il y avait aussi quelque chose de particulier. En essayant différentes valeurs pour max_vec, nous avons constaté que les performances diminuaient strictement à mesure que la valeur augmentait:
Tester le débit contre max_vec | ||
max_vec | écrire | lire |
2 | 8,080 Mo / s | 15,460 Mo / s |
4 | 5,540 Mo / s | 13,670 Mo / s |
8 | 4,540 Mo / s | 13,430 Mo / s |
C'était inattendu. Finalement, nous avons décidé de revoir les données. Clairement, il nous manquait quelque chose. J'ai commencé à parcourir les données iostat à partir d'une multitude de tests de performance et j'ai rapidement découvert la pièce manquante: le les lecteurs n'étaient pas un peu plus lent. Exactement UN le lecteur était beaucoup Ralentissez:
Quand j'ai montré ce complot à un ingénieur d'Intel, il a eu un de ces moments «eureka». Le problème n'était pas dans VMD après tout - c'était dans un pilote pour un périphérique PCIe complètement séparé, un module de gestion intégré dans un commutateur Microsemi PCIe.
Rappelez-vous comment un VMD agit comme une sorte d’intermédiaire et gère ses périphériques connectés via un ensemble partagé de vecteurs d’interruption. Lorsque le VMD reçoit une interruption sur l'un de ces vecteurs, il ne sait pas nécessairement quel périphérique est la cible réelle. Donc, il doit effectivement invoquer les gestionnaires d'interruptions pour tous les appareils partageant ce vecteur. Si l'un de ces gestionnaires d'interruptions était plus lent que les autres, le reste serait simplement obligé d'attendre.
C'est exactement ce qui se passait. L’augmentation de max_vec au-delà de 2 a considérablement aggravé les choses, c’est que l’attribution de plus de vecteurs d’interruption à chaque périphérique augmentait la probabilité qu’un (ou plus!) SSD finisse par partager un vecteur avec le commutateur Microsemi. De plus, comme une seule opération d'écriture dans le système de fichiers de Qumulo sera codée en effacement sur plusieurs unités de stockage pour la protection des données, si un seul disque impliqué dans une écriture est lent, l'écriture entière sera lente.
Voici une version condensée du gestionnaire d’interruptions fautif, trouvée dans drivers / pci / switch / switchtec.c dans la source du noyau Linux:
static irqreturn_t switchtec_event_isr (int irq, void * dev)
{
struct switchtec_dev * stdev = dev;
u32 reg;
/ *… * /
reg = ioread32 (& stdev-> mmio_part_cfg-> mrpc_comp_hdr);
si (reg & SWITCHTEC_EVENT_OCCURRED) {
/ *… * /
iowrite32 (reg, & stdev-> mmio_part_cfg-> mrpc_comp_hdr);
}
/ *… * /
}
Consultez ces appels vers ioread32 et iowrite32, en ciblant une adresse d'E / S mappée en mémoire sur le commutateur lui-même. Dans le cadre de la gestion d’une interruption, ce pilote effectue des E / S réelles sur le bus PCIe (!).
S'il devait y avoir un seul commandement d'écrire des pilotes de périphérique, un concurrent sérieux serait: «Vous ne ferez pas plus de travail que ce qui est absolument nécessaire dans un gestionnaire d'interruptions». Peut-être qu'attendre des E / S n'est pas une grosse affaire pour ce périphérique , mais cela devient un gros problème quand il finit par partager un vecteur d'interruption avec quelque chose d'extrêmement sensible au temps de latence!
Heureusement, la solution à tout ce problème était simple: ne chargez pas le module noyau switchtec. Nous n'avions besoin d'aucune de ses fonctionnalités, et sans ce gestionnaire d'interruption lent dans le mix, nous étions de nouveau opérationnels à pleine vitesse - avec nos lumières clignotantes et colorées.
La morale de l'histoire
Les valeurs aberrantes peuvent être extrêmement importantes.
C'est une de ces choses que presque tout le monde «sait», mais c'est une chose facile à oublier, surtout lorsque vous poursuivez une hypothèse. Les moyennes sont utiles, après tout - ce chiffre peut vous en dire long sur un phénomène. Mais ne tirez pas trop de conclusions de la moyenne à moins de comprendre la distribution sous-jacente!