Chez Qumulo, nous utilisons fio, un outil d'analyse comparative des E / S open source populaire, pour mesurer les performances de notre système de fichiers et détecter les régressions. C'est en quelque sorte un couteau suisse, prenant en charge une grande variété de modes et de modèles d'E / S; l'une de ses fonctionnalités pratiques est un mode client / serveur, qui peut diriger le trafic vers un cluster de stockage à partir de plusieurs machines simultanément. Ceci est utile pour simuler de nombreuses charges de travail de stockage réelles, telles qu'une ferme de nœuds de rendu écrivant tous sur un cluster de stockage - cela nous permet de caractériser le débit que l'un de nos clusters peut supporter.

Afin de détecter de manière fiable les régressions, il est important d'avoir des mesures cohérentes: à moins qu'un changement de logiciel ne rend quelque chose plus rapide ou plus lent, un bon benchmark devrait donner à peu près le même résultat à chaque fois. Voici trois meilleures pratiques que nous suivons pour vous aider à obtenir des résultats fluides et cohérents qui facilitent la détection des écarts importants.

1. Utilisez l' fio mode basé sur le temps

Le premier est assez simple. fio a deux méthodes de base pour contrôler la quantité de choses que chaque travail fait: basée sur la taille et basée sur le temps. En mode basé sur la taille, chaque thread écrira (ou lira) une quantité fixe de données, puis s'arrêtera. La quantité totale de données transférées par tous les travaux, divisée par le temps nécessaire à la fin du dernier travail, correspond à votre débit mesuré.

Cette approche pose un problème: tous les travaux ne termineront pas leur travail en même temps. Les fluctuations ordinaires de la planification des processus peuvent signifier qu'un travail obtient une part légèrement plus grande du débit du cluster que d'autres, ou plus que sa juste part de bande passante réseau. Ce diagramme montre quatre travaux transférant chacun 10 gibioctets de données:

mesure de la performance fio

Étant donné qu'une tâche a pris un peu plus de temps que les autres à terminer, notre intervalle de mesure comprend une durée courte mais imprévisible pendant laquelle une seule tâche était en cours d'exécution. Cela introduit du bruit dans les résultats.

La solution à ce problème réside dans les paramètres du travail fio basé sur le temps et d'exécution. Par exemple, donner time_based = 1 et runtime = 60 s entraînera l'exécution de tous les travaux pendant soixante secondes, puis leur arrêt. Cela permet de garantir que l'intervalle de mesure fait toujours fonctionner le cluster à pleine charge, ce qui permet des mesures plus cohérentes.

2. Introduisez une barrière avec exec_prerun

Les travaux qui se terminent tôt ou tard ne sont pas la seule source de gigue de mesure! Il y a un autre problème, plus subtil: chaque tâche fio ne commence pas à faire son travail immédiatement. Tout d'abord, il effectue une configuration et un entretien ménager, collectant des informations sur les fichiers sur lesquels il travaillera, émettant état et autres demandes de métadonnées. Cela peut prendre un peu de temps, surtout s'il y a beaucoup de fichiers dans le travail, et le temps que chaque travail prend pour se préparer peut varier pour les mêmes raisons mentionnées ci-dessus. L'exécution de chaque tâche pendant une durée déterminée est excellente, mais les tâches ne se termineront toujours pas en même temps si elles ne le font pas Commencez en même temps!

La solution à ce problème est un peu plus complexe, car fio lui-même ne dispose d'aucun mécanisme pour coordonner les heures de début des travaux. Heureusement, il est à la hauteur de son nom de «testeur d'E / S flexible» ici, et fournit exactement le couteau suisse dont nous avons besoin: exec_prerun, un paramètre de travail vous permettant de fournir une commande qui s'exécutera immédiatement avant que le travail ne commence son travail.

Vous connaissez peut-être une technique de multitraitement de base connue sous le nom de barrière: plusieurs processus peuvent attendre à la barrière; la barrière sait à combien de participants s'attendre et ne permettra à aucun processus de se poursuivre tant qu'ils n'auront pas tous attendu.

Pour la coordination entre plusieurs machines, nous avons créé une implémentation de barrière TCP simple en Python. Il n'y a pas grand-chose à faire - nous avons un serveur qui attend N connexions:

def serveur (point final, N):

    s = socket.socket (AF_INET, socket.SOCK_STREAM)

    s.bind (point final)

    à l'écoute (N)

    connexions = []

    pour _ in plage (N):

        connections.append (s.accept ())

    # Une fois que nous sommes ici, nous savons que tout le monde est à la fête!

    pour conn, _ in les liaisons:

        conn.sendall (b'go! ')

Et un client qui se connecte simplement au serveur et attend qu'on lui dise qu'il peut partir:

def client (point final):

    s = socket.socket (AF_INET, socket.SOCK_STREAM)

    s.connect (point final)

    # Cela bloquera jusqu'à ce que le serveur réponde:

    s.recv (3)

Le code ci-dessus est simplifié pour plus de clarté - en réalité, bien sûr, il y a plus de gestion des erreurs. Ensuite, tout ce que nous avons à faire est de mettre quelque chose comme ça dans notre fichier de travail:

exec_prerun =. / barrière_client.py

… Et maintenant non seulement nos travaux fonctionneront pendant la même durée, ils seront tous Commencez fonctionnant en même temps. Mais bien sûr, il y a plus!

3. Restreindre le tampon client au plafond fsync () déraper

Enfin, il existe une source de variabilité propre aux emplois écriture Les données. Par défaut sur la plupart des systèmes d'exploitation (et avec fio), les données écrites dans les fichiers sont tamponné; c'est un écrire () syscall placera les données dans une mémoire tampon système, puis retournera immédiatement. Le système d'exploitation videra ensuite ces données de manière asynchrone vers le stockage, qu'il s'agisse d'un disque local ou d'un stockage distant sur un réseau.

Pourquoi est-ce important? Eh bien, la mise en mémoire tampon imprudente dans un benchmark est de la triche! Si fio pense que 300 Go de données sont écrits en 60 secondes, mais que 50 Go de ces données sont toujours mis en mémoire tampon localement car les machines clientes ont beaucoup de RAM, cela surestimera le débit du stockage testé. Pour lutter contre cela, nous utilisons le end_fsync paramètre de travail pour garantir que chaque travail vide ses tampons une fois l'écriture terminée.

Malheureusement, cela a un autre effet secondaire: le temps qu'il faut pour fsync () n'est pas soumis à fiola minuterie de travail de - une autre source de variabilité! Pour aggraver les choses, Linux utilise par défaut un pourcentage de la mémoire disponible du système pour décider quand il commencera le vidage en arrière-plan… et toutes les machines de notre pool de clients de laboratoire n'ont pas la même quantité de mémoire!

Cependant, résoudre ce problème est assez simple. Nous pouvons simplement dire à Linux exactement la quantité de tampon à utiliser:

sysctl -w vm.dirty_bytes = 2000000000

sysctl -w vm.dirty_background_bytes = 1000000000

Dans ce cas, nous avons spécifié que le vidage en arrière-plan doit commencer lorsque le tampon total atteint 1 Go, et à 2 Go, il doit commencer à bloquer écrire () appels. Les valeurs exactes ici ne sont pas critiques: elles doivent simplement être 1) les mêmes pour chaque client, 2) suffisamment petites pour qu'il ne soit pas possible de passer un temps excessif dans fsync ()et 3) suffisamment grand pour ne pas gêner les performances. Ces valeurs fonctionnent bien pour les tests que nous exécutons - les clients conduisent toujours la charge à pleine vitesse, mais le temps nécessaire pour rincer à la fin est beaucoup plus cohérent, améliorant le rapport signal / bruit du test.

(Remarque: Vous pouvez, bien sûr, utiliser les E / S directes / sans tampon avec fio, qui est une autre manière d'échapper à ce problème. Mais cela modifie les caractéristiques de la charge de travail d'autres manières, et la majorité des applications utilisent des E / S tamponnées, nous voulons donc avoir des tests qui simulent le cas courant.)

Conclusion

C'est ainsi que nous assurons notre fioles tests de performance basés sur des résultats lisses et cohérents. Avoir un bon rapport signal / bruit nous permet de détecter et de corriger beaucoup plus facilement les régressions de performances - et, bien sûr, cela nous aide également à suivre les améliorations de performances à mesure que nous continuons à accélérer notre système de fichiers.

En savoir plus sur fio.

Contact

Demandez une démo ou un essai gratuit de la plate-forme de données de fichiers de Qumulo pour voir une gestion des données de fichiers radicalement simple à l'échelle du pétaoctet. 

Abonnez-vous au blog Qumulo pour les témoignages de clients, les informations techniques, les actualités produits et les meilleures pratiques.