Aller au contenu

Fonctionnement d'un ordinateur/Les mémoires de masse : généralités

Un livre de Wikilivres.

Maintenant que nous savons tout ce qu'il y a à savoir sur les entrées-sorties, ainsi que sur les mémoires, nous allons passer aux mémoires utilisées pour le stockage. Elles regroupent beaucoup de mémoires différentes : disques durs, disques SSD, clés UBS, CD et DVD-ROM, et bien d'autres. Ce sont des mémoires de grande capacité, qui servent à stocker de grosses quantités de données sur un temps assez long. Elles conservent des données qui ne doivent pas être effacés et sont donc des mémoires de stockage permanent (on dit qu'il s'agit de mémoires non-volatiles). Concrètement, elles conservent leurs données mêmes quand l'ordinateur est éteint, ce qui en fait des mémoires non-volatiles. Du fait de leur grande capacité, elles sont très lentes.

Dans ce chapitre, nous allons séparer le tout en deux sections : celle qui explore l’intérieur d'une mémoire de masse, et celle qui explore son interface externe. Par interface externe, on veut dire comment une mémoire de masse communique avec le reste de l'ordinateur. Tout comme pour le processeur ou une mémoire, il y a une séparation entre la micro-architecture et l'architecture externe. L'interface d'une mémoire de masse varie beaucoup suivant le bus utilisé. Par contre, peu importe le bus utilisé, toutes les mémoires de masse ont peu ou prou la même manière de communiquer avec le reste de l'ordinateur. Et c'en est au point où des mémoires de masse très différents peuvent utiliser le même bus pour communiquer avec l'ordinateur. Par exemple, le bus P-ATA était utilisé à la fois par les anciens disques durs, les lecteurs/graveurs de CD/DVD, et les premiers SSD. Il s'agit de mémoires très différentes dans leur fonctionnement interne : les supports de mémorisation ne sont pas les mêmes (magnétique pour les HDD, électronique pour les SSD, optique pour les CD/DVD), pourtant la manière de communiquer avec l'ordinateur était la même.

L'interface externe d'une mémoire de masse

[modifier | modifier le wikicode]

Là où les mémoires normales sont directement connectées sur le bus système, les mémoires de masse sont accédées à travers les ports d'entrée-sorties. Pour simplifier, elles ont la particularité d'être des périphériques, ou d'être connectés à la carte mère comme le sont les cartes d'extension. Leur lenteur pachydermique fait qu'elles n'ont pas besoin de communiquer directement avec le processeur, ce qui fait qu'il est plus pratique d'en faire de véritables périphériques. Elles sont à la fois des mémoires, mais aussi des périphériques/IO. C'est la raison pour laquelle nous allons en parler à ce moment-ci du cours, plutôt que dans la section sur les mémoires : en parler demande de faire appel à la fois aux concepts vus dans les chapitres sur les mémoires, et aux concepts des entrées-sorties. Tout ce qu'il faut retenir, c'est que la communication avec une mémoire de masse n'est pas très différente de la communication avec un périphérique. Il y a un contrôleur de périphérique, des registres d’interfaçage, du Direct Memory Access, des interruptions, etc. Mais les mémoires de masse ont cependant quelques spécificités, notamment la présence de blocs et d'adresses mémoire.

Les blocs et secteurs

[modifier | modifier le wikicode]

Du point de vue de l'ordinateur, une mémoire de masse est assez similaire à une mémoire normale. Elle est composée de plusieurs mots mémoire, chacun avec sa propre adresse. Mais la terminologie est quelque peu différente. Si le terme d'adresse est toujours utilisé, les mots mémoire des mémoires de masse sont appelés des blocs. Ils sont aussi appelés des secteurs pour les disques durs et médias optiques. Il s'agit de bloc de données de taille fixe, dont la taille est bien supérieure aux mots mémoire des RAM/ROM usuelles. Un bloc fait généralement 512 octets et les mémoires de masse récentes ont des blocs pouvant aller jusqu'à plusieurs kibioctets, là où les RAM/ROM ont usuellement des mots de mémoires de quelques octets, grand maximum 128. En soi, rien d'étonnant à avoir des blocs de grande taille, vu que les mémoires de masse ont une grande capacité : avec une grande capacité, avoir une taille de bloc importante permet de garder un nombre raisonnable d'adresses.

La taille d'un bloc est un compromis

[modifier | modifier le wikicode]

L'usage de blocs de grande taille est très adapté au stockage des fichiers, raison principale de l'existence des mémoires de masse. Les fichiers sont découpés en morceaux qui font la même taille qu'un bloc et le système d'exploitation réserve assez de blocs pour stocker tout le fichier. Vous remarquerez qu'en faisant ainsi, la taille prise par un fichier sur une mémoire de masse sera toujours un multiple de la taille d'un bloc. Elle sera égale à la taille d'un bloc, multipliée par le nombre de blocs utilisés. Mais cela pose un léger problème pour les petits fichiers. Par exemple, imaginons un fichier de 50 octets, enregistré sur une mémoire de masse dont le bloc fait 4 kibioctets : on gâchera une bonne partie du bloc à rien. La même chose a lieu quand les fichiers prennent un faible nombre de blocs. Par exemple, pour un fichier de 9 kibioctets et des blocs de 4 Ko, trois secteurs seront utilisés, dont le dernier ne contiendra qu'1 Ko de données utiles, 3 Ko étant gâchés. Ce phénomène de gâchis de mémoire, appelé la fragmentation interne, est d'autant plus important que la taille des blocs est importante. Utiliser des blocs de grande taille est donc une mauvaise idée.

Mais utiliser beaucoup de blocs de petite taille n'est pas sans défaut non plus. La première raison à cela est que, à capacité égale, des plus petits blocs signifie plus de blocs. Et diviser une mémoire de masse en un grand nombre de blocs rendra l'adressage plus compliqué. Chaque bloc a en effet une adresse, un numéro, et plus de blocs signifie plus d'adresses à gérer, avec tous les défauts que cela peut avoir : des circuits d'adressages plus compliqués et plus gourmands en transistors, des adresses plus longues et donc des trames plus longues, etc. Un autre défaut tient dans les performances : lire de grandes quantités de données est plus rapide quand on a des blocs assez gros. Si un gros fichier est répartit sur 1000 blocs, sa lecture totale demandera plus de temps que s'il est sur seulement 100 blocs, car il faudra faire moins d'opérations de lecture/écriture : 1000 dans le premier cas, seulement 100 dans le second. Moins de commandes de lecture/écriture à envoyer signifie que le bus de communication sera mieux utilisé et que son débit sera surtout consacré à transférer des données. Le débit du bus est important dans les performances des mémoires de masse. Pour résumer, la taille des blocs est un compromis entre débit de la mémoire et gâchis de mémoire.

L'advanced format

[modifier | modifier le wikicode]

Pour les disques durs anciens, les secteurs font une taille de 512 octets. Les CD et DVD avaient des secteurs de 2048 octets, 4 fois plus grands que ceux des disques durs. De nos jours, disques durs et SSD utilisent des secteurs plus gros, généralement de 4096 octets. La taille de 512 octets est appelée la taille standard, alors que secteurs plus gros sont appelés des secteurs de type advanced format. Ce format autorise des secteurs de 4096, 4112, 4160, et 4224 octets. La raison derrière ce changement est en grande partie liée à une question d'efficacité du stockage sur le support de mémorisation, comme nous allons immédiatement le voir dans la section sur la microarchitecture des mémoires de masse.

Mais utiliser des secteurs de 4 kibioctets posait des problèmes de compatibilité, avec les systèmes d'exploitation ou les cartes mères conçues pour des secteurs standards. Pour éviter tout problème, les premiers disques durs en advanced format utilisaient des mécanismes matériels de compatibilité. Ils émulaient un disque dur en secteur standard, alors que leurs secteurs étaient en advanced format. Pour les lectures, cela ne faisait pas vraiment de différences en termes de performance. Le disque dur lisait un secteur de 4 kibioctets, et sélectionnait les 512 octets demandés. Le secteur 4k entier pouvait être placé dans une mémoire cache, ce qui accélérait les lectures quand on accédait à des secteurs 512o consécutifs : les secteurs suivant étaient lus depuis ce cache et non depuis le disque dur. Pour les écritures, les choses étaient plus compliquées. Au lieu de simplement écrire un secteur 512 octets, il fallait : copier le secteur 4K dans le cache, modifier les 512 octets écrit dans ce cache, et réécrire tout le secteur 4k sur le disque dur. En soi, diverses optimisations au niveau de cache permettaient de limiter la casse, mais cela ralentissait les écritures.

Un autre point est qu'il fallait éviter des problèmes d'alignement. La taille de 4 kibioctets avait était choisie, entre autres, car c'est la taille standard des clusters du système d'exploitation. Celui-ci découpe les fichiers en clutsers de 4 kibioctets, et gérait des clusters au lieu de secteurs. Utiliser une taille de 4k pour les clusters et les secteurs parait être une très bonne idée. Mais il faut que les secteurs et les clusters soient alignés, c’est-à-dire qu'un secteur doit correspondre à un cluster. Il ne faut pas qu'un cluster soit à cheval sur deux secteurs, comme illustré dans le schéma ci-dessous. Sans ce genre de précautions, la perte de performance est drastique.

Secteurs et clusters non-alignés.

De nos jours, cette émulation a disparu et les systèmes d'exploitation modernes, ainsi que les BIOS, gèrent parfaitement des secteurs advanced format natifs.

Les commandes d'entrée-sortie

[modifier | modifier le wikicode]

La communication avec une mémoire de masse est la même qu'avec tout périphérique : l'ordinateur envoie une commande, qui demande à la mémoire de masse de faire quelque chose, et celle-ci l’exécute. La commande en question est soit une demande de lecture ou écriture, soit autre chose. Il y a beaucoup de commandes de configuration : pour configurer la mémoire de masse, pour déterminer l'état de la mémoire de masse en interrogeant le registre d'état du contrôleur de périphérique, etc. Mais les principales sont les commandes de lecture et d'écriture, qui permettent de lire ou d'écrire un bloc. Toute commande de lecture/écriture manipule un bloc entier. Il est impossible d'écrire seulement une portion de bloc, ou d'en lire seulement quelques octets.

Il existe des commandes de lecture/écriture qui permettent de lire/écrire plusieurs blocs consécutifs en mémoire, sur le même modèle que les accès en rafales des mémoires RAM.

Une commande de lecture demande de lire un bloc depuis la mémoire de masse : elle envoie l'adresse du bloc à lire, éventuellement quelques autres informations. La commande est encodée sur un certain nombre de bits, dont des bits de commande qui indiquent si la commande est une lecture/écriture/autre. Une commande d'écriture envoie la donnée à écrire, l'adresse du bloc à écrire, et éventuellement d'autres informations. Toutes les mémoires gèrent au minimum les commandes de lecture, et la plupart gèrent les commandes en écriture (sauf pour les CD/DVD non-réinscriptibles). Dans certains cas, la commande d'écriture ne contient pas la donnée à écrire, mais l'adresse de cette donnée dans la RAM principale. La donnée à écrire est alors stockée en mémoire RAM, séparée de la commande, et le transfert s'effectue par Direct Memory Acess, ou autre.

Évidemment, les mémoires de masse sont connectées au reste de l'ordinateur par un bus, tout comme pour les mémoires RAM/ROM. Sauf que si les RAM/ROM ont des mots mémoire qui ont la même taille que celle du bus, la taille d'un bloc est largement supérieure à la taille du bus pour une mémoire de masse. Les données d'un bloc sont donc transférées en plusieurs fois, morceau par morceau. Et c'est là que ce qu'on a vu sur les entrées-sorties rentre en jeu. Les transferts de données avec une mémoire de masse se font par une communication sur le bus, sous la forme d'une trame. C'est tout l'opposé de ce qu'on avait pour les RAM/ROM parallèles, où tout transfert de donnée se faisait en une fois, en un cycle d'horloge.

La mémoire de masse reçoit une commande et l'exécute. Une commande demande de faire des transferts entre mémoire RAM et mémoire de masse, qui passent souvent par DMA. Pour une lecture, le bloc lu ou est copié en mémoire RAM, morceau par morceau, généralement via DMA. Pour l'écriture, la donnée à écrire est en RAM et est transmise à la mémoire de masse morceau par morceau, là encore via DMA. Une fois la commande exécutée, la mémoire de masse prévient le processeur qu'elle est terminée, soit avec une interruption, soit en mettant à jour le registre d'état du contrôleur de périphérique.

La micro-architecture d'une mémoire de masse

[modifier | modifier le wikicode]

L'intérieur d'une mémoire de masse ressemble beaucoup à celui d'une mémoire normale : on trouve un support de mémorisation et éventuellement des circuits annexes.

Le support de mémorisation : supports magnétiques et optiques

[modifier | modifier le wikicode]

Toute mémoire de masse contient un support de mémorisation, à savoir quelque chose de physique qui stocke les données enregistrées dessus. Celui peut être :

  • magnétique, comme dans les disques durs ou les fameuses disquettes (totalement obsolètes de nos jours) ;
  • électroniques, comme dans les mémoires Flash utilisées dans les clés USB et disques durs SSD ;
  • optiques, comme dans les CD-ROM, DVD-ROM, et autres CD du genre ;
  • mécanique ou acoustique, dans quelques mémoires très anciennes et rarement utilisées de nos jours, comme les rubans perforés et quelques autres.

Les blocs sont mémorisés sur le support de mémorisation, qui est soit magnétique (HDD), soit optique (CD/DVD), soit électronique (SSD). Le support de mémorisation est généralement découpé en blocs, mais il arrive rarement que ce ne soit pas le cas. En fait, sur les SSD, le découpage en blocs n'est pas si évident quand on regarde le support de mémorisation. Dans ce cas, les blocs sont une vue de l'esprit, un moyen de transférer des données entre l'ordinateur et une mémoire de masse, mais pas une réalité. Ce sont des abstractions qui permettent de communiquer avec la mémoire de masse, pas quelque chose de physique. Mais sur les disques durs et les médias optiques, le support de mémorisation est bel et bien découpé en blocs. Dans ce cas, on parle alors de secteur, bien que la terminologie ne soit pas forcément très stricte.

Un secteur contient les données du secteur, mais aussi d'autres informations utiles pour la mémoire de masse. En premier lieu, on trouve des informations qui permettent d'indiquer le début du secteur. Les disques durs et médias optiques sont formés d'un support magnétique continu, qu'il faut découper en secteur en indiquant physiquement là où commence le secteur. Avant les données, on trouve donc un préambule que le contrôleur utilise pour déterminer la position des secteurs. Après les données, on trouve des bits d'ECC, à savoir des bits de correction/détection d'erreur, qui permettent de vérifier si les données sont valides ou corrompues. Il faut noter que les bits d'ECC sont présents sur les SSD, mais pas le préambule.

Secteur.

Le préambule et les bits d'ECC sont généralement une petite perte sèche. Une partie du support magnétique/optique est gâchée pour stocker les préambules et les bits d'ECC. Et la taille d'un secteur impacte cette perte. Plus les secteurs sont gros, moins on a de secteurs à capacité égale, donc on a moins de préambules et moins de pertes. L'espace mémoire pris par les bits d'ECC n'est pas censé changer en fonction du nombre de secteurs. Mais augmenter la taille des secteurs permet d'utiliser des techniques d'ECC plus efficaces, qui prennent moins de bits pour une qualité équivalent. En clair, plus la taille d'un secteur est grande, moins on a de pertes et plus la capacité effective est importante. C'est d'ailleurs la raison qui a poussé les fabricants de disques durs et de CD/DVD à dépasser la taille standard de 512 octets. Par exemple, le passage à des secteurs de 4 kibictets pour les disques durs modernes visait à réduire cette perte sèche.

Comparaison de la perte sèche entre des secteurs standard et des secteurs de type Advanced format (4Kib).

Le contrôleur de périphérique d'une mémoire de masse

[modifier | modifier le wikicode]

Sur certaines mémoires de masse, on n'a rien d'autre qu'un support de mémorisation. C'est le cas des mémoires optiques : un CD ou DVD est un simple support de mémorisation, sans contrôleur électronique. Mais les autres mémoires intègrent de l'électronique.

Pour les CD et DVD, cette électronique est présente dans le lecteur/graveur de CD/DVD.

Cette électronique peut être découpée en deux circuits séparés : un contrôleur mémoire et un circuit d'interface avec le bus. Les seules différences tiennent dans la complexité de ces différents composants. Le circuit d'interface avec le bus est beaucoup plus complexe, car il doit communiquer avec des bus comme le PCI-Express, l'USB, ou autres, qui sont beaucoup plus complexes que les bus mémoires normaux. Le contrôleur mémoire n'est en rien un décodeur, mais est un circuit beaucoup plus complexe et bourré d'électronique. Dans la plupart des cas, ce contrôleur est un véritable processeur couplé à une RAM et une ROM. La ROM contient un firmware qui peut être mis à jour si besoin.

Microarchitecture d'une mémoire de masse

Le disk buffer

[modifier | modifier le wikicode]

Une mémoire de masse est beaucoup plus lente que le reste de l'ordinateur, sans compter que les transferts de données doivent se faire quand le bus est libre. Il arrive que le disque dur reçoive une commande de lecture, l’exécute, mais que le bus soit occupé alors que la lecture a lieu dans le support de mémorisation. Idem pour les écritures : le support de mémorisation peut être occupé, alors qu'une commande d'écriture soit en cours de transfert sur le bus. Pour éviter tout problème, les mémoires de masse incorporent une mémoire tampon appelée le disk buffer, ou encore le cache disque intégré.

Dans sa version la plus simple, le disk buffer contient un seul bloc. Il est alors une simple mémoire tampon qui sert d'intermédiaire entre le support de mémorisation et le bus. Lors d'une lecture, les données lues depuis le support de mémorisation sont copiées dans le disk buffer, puis attendent dedans que le bus soit libre. Pareil lors d'une écriture : les données à écrire sont accumulées dans le disk buffer, et sont copiées sur le support de mémorisation quand celui-ci est libre.

Disk buffer fusionné avec un cache d'écriture.

En clair, avec un disk buffer, une écriture se fait en deux temps : le bloc est écrit d'abord dans le disk buffer, puis transféré sur le support de mémorisation quand celui-ci est libre. Et cela permet une optimisation assez intéressante : le disque dur prévient le processeur quand le bloc est écrit dans le disk buffer, pas dans le support de mémorisation. L'écriture est donc plus rapide, même si elle est en réalité différée quand le contrôleur de disque l'a décidé. Mais cette optimisation pose un problème en cas de coupure de courant. Les données à écrire vont attendre durant un moment avant que les plateaux soient libres pour démarrer l'écriture. Si jamais une coupure de courant se produit, les données présentes dans la mémoire tampon, mais pas encore écrites sur le disque dur, sont perdues.

En théorie, le disk buffer ne contient qu'un seul bloc. Mais sur les mémoires de masse à haute performance, le disk buffer est modifié de manière à pouvoir contenir plusieurs blocs. Cela permet diverses optimisations pour améliorer les performances. Une première possibilité d'optimisation demande de séparer le disk buffer en deux : un disk buffer spécialisé dans les écritures, et un autre pour les lectures.

Le disk buffer pour les lectures est appelé improprement le cache de lecture, mais le terme le plus adapté serait plutôt tampon de prélecture. Il ne s'agit pas d'un cache, car il est rare qu'un bloc soit relu sous peu. Son rôle est d'utiliser la technique dite du préchargement. Avec cette technique, le support de mémorisation accède successivement non pas à un seul bloc, mais à plusieurs blocs consécutifs. Ceux-ci sont alors chargés dans le disk buffer, et sont disponibles à l'avance pour de futures lectures. Le préchargement marche très bien si jamais on précharge les blocs suivants, pendant que la mémoire de masse attend que le bus soit libre, ou que le bloc lu est transféré.

Disk buffer avec cache de lecture et préchargement

Le disk buffer spécialisé dans les écritures est aussi modifié de manière à pouvoir gérer plusieurs blocs en même temps. Il porte alors le nom de write buffer, ou encore de tampon d'écriture. Le tampon d'écriture est une mémoire FIFO, qui mémorise plusieurs écritures en attente. L'idée est de mettre en attente un grand nombre d'écriture, de manière à prioriser les lectures. Ainsi, si on doit effectuer un grand nombre de lectures/écritures, les écritures sont mises en attente dans le tampon d'écriture, alors que le support de mémorisation est utilisé pour les lectures en priorité. Les écritures ont lieu soit quand le support de mémorisation est libre, soit quand il est plein et que les écritures doivent avoir lieu. A noter que si on veut lire un bloc récemment écrit, il se peut que la donnée écrite soit en réalité dans le tampon d'écriture, mais pas encore sur le support de mémorisation. Dans ce cas, la donnée doit être lue depuis le tampon d'écriture.

Diverses optimisations permettent d'optimiser au mieux les écritures sur le support de mémorisation, avec l'aide du tampon d'écriture. L'optimisation principale permet d'accélérer certaines écritures successives. Elle porte le nom de combinaison d'écriture. Comme son nom l'indique, elle consiste en la fusion de plusieurs écritures en une seule. Si plusieurs écritures dans un même bloc sont dans le tampon d'écriture, alors seule la toute dernière est envoyée au support de mémorisation.

Tampon d'écriture d'une mémoire de masse

Il est possible de fusionner le tampon de prélecture et le tampon d'écriture, ce qui donne un véritable cache, capable de mémoriser plusieurs blocs. Il peut ainsi servir de cache pour les accès en lecture : si jamais une donnée est lue plusieurs fois de suite, le premier accès charge le bloc lu dans le cache, les accès ultérieurs relisent le bloc depuis le cache, ce qui est plus rapide. Mais une telle situation est assez rare. On peut aussi précharger les blocs proches de celui lu, afin de faciliter des lectures ultérieures à ces blocs préchargés. Un tel cache facilite l'implémentation de la combinaison d'écriture : si jamais un bloc est modifié plusieurs fois de suite, ces modifications se font dans le cache et seul le résultat final est ensuite écrit dans le support de mémorisation : on a en quelque sorte fusionné plusieurs écritures en une seule. Des écritures dans le support de mémorisation ont été évitées, ce qui laisse la place pour d'autres commandes.

La power loss protection

[modifier | modifier le wikicode]

Une mémoire de masse peut perdre des données quand on coupe le courant, en raison de la présence du disk buffer. Le disk buffer est totalement effacé lors d'une coupure de courant, vu qu'il est fait avec des SRAM/DRAM. Le contenu du disk buffer doit idéalement être totalement transféré sur le support de mémorisation avant une coupure de courant, sans quoi des données peuvent être perdues. Par exemple, une écriture dans un fichier peut être mise en attente dans le disk buffer et perdue lors d'une coupure de courant, alors que le système d'exploitation a déjà mis à jour ses données internes après une écriture (listes de secteurs, taille du fichier, etc). La donnée est alors perdue, même si l'OS ne voit rien.

Pour éviter ce genre de problème, la solution idéale est de désactiver la mise en attente des écritures dans le disk buffer. Toute écriture a alors lieu immédiatement sur le support de mémorisation. Une option du système d'exploitation permet de faire ce genre de choses, mais sa désactivation engendre de grosses pertes de performance. Une autre solution est purement matérielle : concevoir la mémoire de masse de manière à gérer le cas d'une perte de courant. Pour cela, on ajoute des condensateurs à la mémoire de masse, qui servent de réservoirs à électricité. En cas de coupure de courant, les condensateurs fournissent du courant assez longtemps pour que la mémoire de masse ait le temps de sauvegarder ce qu'il faut. La mémoire de masse monitore en permanence le statut de l’alimentation. Si elle est coupée, la mémoire de masse stoppe immédiatement tout ce qu'elle faisait et démarre immédiatement la procédure de sauvegarde. Mais toutes les mémoires de masse n'ont pas cette technique de protection, appelé la power loss protection. Seule une minorité marketée pour le fait.

La performance des mémoires de masse

[modifier | modifier le wikicode]

Les caractéristiques d'une mémoire de masse sont plus ou moins les mêmes que pour une mémoire normale : elle a une capacité mémoire, un temps d'accès et un débit binaire. Nous allons mettre de côté la capacité mémoire, sur laquelle il n'y a pas grand-chose à dire, et nous concentrer sur les deux derniers points. Nous avions déjà abordé tout cela dans le chapitre sur "La performance d'un ordinateur", mais quelques rappels ne font pas de mal : le temps d'accès est le temps que met la mémoire pour répondre à une demande de lecture/écriture. Le débit binaire est la quantité de données pouvant être lue/écrite par seconde, exprimée en octets. Idéalement, une mémoire doit avoir un temps d'accès faible, et un débit binaire élevé. Les mémoires de masse ont un temps d'accès élevé, du fait de leur grande capacité (hiérarchie mémoire). Par contre, elles ont généralement un bon débit binaire. La plupart des optimisations des mémoires de masse visent à augmenter leur débit, et non à réduire un temps d'accès de toute façon trop élevé.

Le nombre d'IOPS

[modifier | modifier le wikicode]

Le débit binaire d'un périphérique est le produit de deux facteurs : le nombre d'opérations de commandes par secondes, et la taille des blocs (qui est la quantité de données échangée par commande). Cela peut se résumer par la formule suivante :

, avec D le débit binaire, IOPS le nombre d'opérations disque par secondes, et T la taille d'un bloc/secteur.

Néanmoins, il s'agit d'une équation théorique, qui ne dit rien sur le nombre d'IOPS. Celui-ci est extrêmement variable et dépend de beaucoup de paramètres. Le plus important est la différence entre les accès séquentiels et aléatoires. Le terme accès séquentiel est assez parlant : il s'agit d'accès où on accède successivement à des données contiguës. Typiquement, il s'agit de balayer une portion de mémoire, en partant d'une adresse, puis en accédant à la suivante, puis à celle qui suit, etc. On accède donc à la mémoire adresse par adresse, dans l'ordre des adresses croissantes ou décroissantes. Par contre, les accès aléatoires sont mal nommés. Ils correspondent à des accès mémoire où des lectures/écritures consécutives accèdent à des adresses éloignées les unes des autres.

Random vs sequential access

Toutes les mémoires de masse ne gèrent pas les accès séquentiels ou aléatoires de la même manière. Prenons le cas des SSD, les fameux Solid State Drive : ils ont de bonnes performances pour les deux type d'accès, avec un léger avantage pour les accès séquentiels. Les disques durs, disquettes et CD/DVD sont différents. Ils ont des performances absolument déplorables pour les accès aléatoires, mais excellents pour des accès séquentiels. Les raisons à cela sont liées à leur fonctionnement interne et à la répartition des données sur le support de mémorisation, et nous verrons cela en détail dans le chapitre sur le disque dur. Toujours est-il que ce détail a son importance pour le système d'exploitation : il a tout intérêt à placer un fichier dans des secteurs contigus, plutôt que dans des secteurs éloignés sur le disque dur. Les accès à des fichiers de grande taille donnent généralement des accès séquentiels, si le système d'exploitation s'est bien débrouillé pour utiliser des secteurs contigus. Par contre, l'accès à de nombreux fichiers de petite taille donne des accès aléatoires, ces fichiers n'étant pas forcément placés les uns après les autres sur le disque dur.

Ensuite, il faut savoir que les performances en lecture et écriture ne sont pas forcément les mêmes. Au final, cela donne cinq possibilités :

IOPS total Nombre de commandes par seconde
Random read IOPS Nombre de commandes de lecture par seconde en accès aléatoire
Random write IOPS Nombre de commandes d'écriture par seconde en accès aléatoire
Sequential read IOPS Nombre de commandes de lecture par seconde en accès séquentiel
Sequential write IOPS Nombre de commandes d'écriture par seconde en accès séquentiel

Le tampon de commande et les optimisations associées

[modifier | modifier le wikicode]

Augmenter la taille des blocs augmente le débit, toutes choses égales par ailleurs, mais cette technique est rarement utilisée. La taille des blocs influence non seulement le débit, mais aussi le gâchis d'espace par fragmentation interne et quelques autres paramètres. Difficile d'augmenter la taille des blocs, celle-ci étant un compromis entre de nombreux paramètres. À la place, la majorité des périphériques incorporent diverses optimisations pour augmenter l'IOPS, ce qui permet un meilleur débit pour une taille de bloc identique.

Si on met de côté les optimisations liées au disk buffer, dont nous avons parlé plus haut, la plus importante est celle dite du tampon de commande. Sans lui, la mémoire de masse exécute chaque commande de lecture/écriture l'une après l'autre. Elle doit attendre qu'une commande soit terminée avant d'en envoyer une autre. Dans ces conditions, le support de mémorisation est sous-utilisé. En effet, l’exécution d'une commande demande une phase de transmission de la commande, son interprétation par le contrôleur de mémoire de masse, l'accès au support de mémorisation, puis une phase d'ACK ou de transfert DMA. Durant les phases d'accès au bus et d’interprétation, le support de mémorisation est inutilisé, alors qu'on pourrait y accéder.

Avec le tampon de commande, la mémoire de masse est capable de recevoir des commandes même si les précédentes ne sont pas terminées. Ainsi, quand une commande a terminé d'accéder au support de mémorisation, la suivante est déjà prête et peut accéder immédiatement au support de mémorisation. Pas besoin d'attendre la transmission et l'interprétation de la commande suivante : elle est déjà là. Évidemment, les commandes anticipées sont mises en attente dans une mémoire tampon et traitées quand le support de mémorisation est libre. La mémoire tampon qui met en attente les commandes est appelée le tampon de commandes.

Tampon de commande d'une mémoire de masse

Avec cette optimisation, le nombre d'IOPS augmente, mais le temps d'accès fait de même. Le temps d'accès augmente car le temps d'attente dans le tampon de commande est techniquement compté dans le temps d'accès. Le temps d'accès total augmente donc, au prix d'un débit plus élevé. Plus la file d'attente sera longue (peut mettre en attente un grand nombre de requêtes), plus le débit sera important, de même que le temps d'accès. Il est possible de formaliser l'amélioration induite par ce tampon de requêtes sur le débit et le temps d'accès avec quelques principes mathématiques relativement simples.