On trouve une multitude d’outils de monitoring et de benchmark en ce qui concerne les performances CPU, IO disque et réseau, en particulier sous Linux. Mais pour les accès mémoire c’est autre chose. On parvient à déterminer facilement la quantité de mémoire disponible et restante, mais pas à mesurer le débit utilisé (vitesse des transferts séquentiels) ni le nombre d’opérations par secondes (mops).

Pourtant cette ressource matérielle devrait être suivie avec attention pour comprendre les performances du système. Dans un monde où le in-memory computing se démocratise, de plus en plus de systèmes dépendent des performances mémoire.

Mise en garde : ce qui suit reflète le niveau de compréhension d’une personne non-experte, et les informations de cette page ne peuvent servir de source fiable en l’état.

Performances matérielles théoriques

Pour commencer, il est bon de se plonger dans les spécifications de votre matériel afin de savoir ce que vous pouvez théoriquement en attendre. La mémoire est principalement définie par :

  • sa génération (ex : DDR3, DDR4),
  • sa cadence (ex : 2400Mhz),
  • ses timings (ex : CL17 ou CAS Latency 17),
  • éventuellement sa quantité.

De là en découle la bande passante théorique exprimée avec la notation PC4-19200 par exemple qui signifie 19 200 Mo/sec. La cadence effective de la mémoire est en réalité imposée par le CPU et la carte mère et son chipset (northbridge). La RAM doit donc être choisie en fonction.

D’autres facteurs interviennent comme par exemple la capacité de la carte mère à fonctionner en dual channel ou quad channel pour démultiplier les performances.

Pour une explication imagée des caractéristiques matérielles, je vous recommande chaudement cet article en anglais, avec notamment deux calculs intéressants sur lesquels je me base.

Bande passante théorique

La formule de calcul de la bande passante théorique est la suivante avec les unités entre parenthèses.
Toutes les DDR modernes ont 2 transferts par cycle donc une mémoire 2400 Mhz aura réellement 1 200 000 000 cycles par seconde. Jusqu’à présent la largeur du bus est 64 bits.

Donc on peut confirmer que pour une barrette de mémoire 2400 Mhz PC4-19200 en single channel cela donne : 1 200 000 000 * 2 * 64 / 8 = 192 E8 bytes/sec soit bien 19 200 Mo/sec. En pratique plusieurs facteurs viendront entacher ces chiffres bien jolis sur le papier.

Nombre d’opérations par seconde

Pour un processus donné la fréquence de la mémoire n’a pas forcément un grand intérêt. On peut comparer l’augmentation de la fréquence avec l’ajout d’une voie sur une autoroute fluide ; s’il n’y a pas de trafic alors il n’y a pas d’intérêt. L’augmentation de la fréquence de la mémoire améliore théoriquement les situations qui remplissent le bus mémoire (cf. article anglais ci-dessus).

Pour un utilisateur, la rapidité de la mémoire dépend plutôt de sa latence exprimée en CAS Latency (ou CL). Le chiffre indiqué CL correspond au nombre de cycles nécessaires entre le moment de la requête et le début de la restitution de la donnée par la mémoire.

Je ne sais pas définir ce qu’est réellement une opération mémoire par seconde mais je m’intéresse aux ordres de grandeur pour comparer des systèmes entre eux avec le même système d’unités. Disons que dans le cadre de cet article, une opération est une requête théorique qui demande à la mémoire de restituer une donnée aléatoire et minimale de 1 mot.

Pour estimer le temps nécessaire à une vraie lecture mémoire, voir la page wikipedia CAS Latency. Ensuite différents facteurs environnementaux viendront altérer les valeurs théoriques comme par exemple les overheads dues au système d’exploitation etc. Les caches de niveau L3 et L1 souffrent eux-aussi de latence comme on peut le voir sur cette page.

Pour de la mémoire 1600 Mhz CL7 cela donne : 1600 ( M cycles/sec) / 7 (cycle/opération) = 228 M opération/sec (à un facteur près).
Pour de la mémoire 2400 Mhz CL17 cela donne : 2400 (M cycles/sec) / 17 (cycle/opération) = 141 M opération/sec (à un facteur près).

Attention : l’article anglais du dessus prend la précaution de comparer les valeurs numériques entre elles sans unités. Ici je déduis les unités de leur formule de calcul pour rester homogène. Je précise tout de même « à un facteur près » puisque dans l’absolu la valeur numérique ne signifie rien.

Obtenir ces données depuis son système

Le programme dmidecode permet d’obtenir de nombreuses informations sur le matériel, ici trois exemples sont fournis.

Première configuration (DDR4 2400 Mhz LRDIMM ECC CL17)

Specs : HP DL360 Gen9, Intel E5-2620v3 et DDR4 2400 Mhz LRDIMM CL17.

On a ici à faire à une barrette ECC 72 bits (64 bits de données et 8 bits de correction d’erreur) de 32 Go dont la fréquence réelle imposée par la carte mère est 1866 Mhz.

En théorie c’est de la PC4-19200 et en pratique c’est de la PC4-14928. En théorie on aurait 141 M opérations/sec et en pratique 109 M opérations/sec (à un facteur près).

Seconde configuration (DDR4 2400 Mhz RDIMM ECC CL17)

Specs : HP DL360 Gen9, Intel E5-2620v3 et DDR4 2400 Mhz RDIMM CL17.

Ici la carte mère impose une fréquence de 1600 Mhz en raison des règles de population des slots DIMM visibles sur le manuel.

En théorie c’est de la PC4-19200 et en pratique PC4-12800. En théorie on a 141 M opérations/sec et en pratique 94 M opérations/sec (à un facteur près).

Troisième configuration (DDR3 1333 Mhz ECC CL9)

Specs : Intel S5500BC avec 2x Xeon X5687 et DDR3 1333 Mhz ECC CL9.

Ici le processeur et la carte mère sont réputés compatibles avec la fréquence 1333 Mhz. En tout cas on ne voit pas de « Configured Clock Speed ».

Les caractéristiques théoriques et pratiques sont identiques : PC3-10600 et 148 M opérations/sec (à un facteur près).

Benchmark de la mémoire

Sous Linux le programme mbw est un moyen très simple de mesurer des vitesses de transfert en mémoire. Un paquet Debian est disponible. Les mesures varient en fonction de la version utilisée comme indiqué sur cet article.

Première configuration (DDR4 @ 1866 Mhz CL17)

Rappels pratiques : PC4-14928 avec 109 M opérations/sec (à un facteur près).

Seconde configuration (DDR4 @ 1600 Mhz RDIMM CL17)

Rappels pratiques : PC4-12800 avec 94 M opérations/sec (à un facteur près).

Troisième configuration (DDR3 @ 1333 Mhz CL9)

Rappels pratiques : PC3-10600 avec 148 M opérations/sec (à un facteur près).

Autre configuration (DDR2 @ 667Mhz CL5)

Rappels pratiques : PC2-5336 avec 133 M opérations/sec (à un facteur près).

Autre configuration (DDR2 @ 533 Mhz CL4)

Rappels pratiques : PC2-4264 avec 133 M opérations/sec (à un facteur près).

 

Trois variantes sont présentées pour copier 16 Mo de données :

  • MEMCPY : primitive c memcpy
  • MCBLOCK : primitive c mempcpy
  • DUMB : affectation des valeurs du tableau avec signe égal

Je me risque à quelques remarques hasardeuses à confirmer et à commenter :

  • On trouve facilement des configurations DDR3 plus performantes qu’en DDR4 en dépit d’une technologie moins avancée et optimisée. La technologie DDR2 est quant à elle dépassée.
  • J’ignore l’effet du single/dual/quad channel sur ce benchmark en particulier. Toutes les configuration de cette page doivent probablement en bénéficier.
  • Avec les primitives MEMCPY et MCBLOCK, il est possible que la seconde configuration soit pénalisée par un faible ratio Freq/CAS Latency.
  • Avec la primitive DUMP, le classement semble dépendre des bandes passantes pratiques : PC4-14928 > PC4-12800 > PC3-10600 > PC2-5336 > PC2-4264.
  • Il y a un facteur 1,8 à 3 entre la bande passante théorique calculée et la bande passante mesurée avec mbw en mode DUMB. Un facteur 2 pourrait venir du fait que mbw mesure une vitesse entre deux tableaux stockés en mémoire d’où une lecture et une écriture concurrentes.

Conclusion

J’ai l’intention de jouer avec les données techniques de mes systèmes pour mieux comprendre les performances obtenues par des applications en mémoire (exemple : cache Redis). Malheureusement, ce dont j’aurais besoin c’est un top ou vmstat qui affiche les débits de lecture/écriture en mémoire ainsi que le nombre de MOPS en temps réel, mais je n’ai pas trouvé. Le programme vmstat pour Solaris et autres UNIX semblait plus complet que la version Linux avec des colonnes pour les pages mémoire. Sous Linux dstat s’en rapproche mais il lui manque des champs.

Étonnamment la bande passante d’un ordinateur DDR2 de 2007 est uniquement 3 à 4 fois moins importante qu’un serveur DDR4 récent, et la DDR3 n’a pas dit son dernier mot en termes de performances. Là où la DDR4 est une réelle avancée, c’est sur la quantité maximum par serveur et la consommation électrique.

Pour finir, il serait intéressant de comparer les MOPS mémoire avec les IOPS des SSD en montant un ramdisk, et en y appliquant un benchmark orienté HDD/HDD comme iozone. Cela a notamment été entrepris par Calypso Systems sur cette présentation.