La taille de la page mémoire par défaut du noyau Linux sur l'architecture x86 était de 4 Ko, je me demande comment cela a été calculé et pourquoi?
La taille de page par défaut est fixée par ce que le MMU (unité de gestion de la mémoire) du CPU prend en charge. En mode protégé 32 bits x86 prend en charge deux types de pages:
Tous les processeurs x86 ne prennent pas en charge les grandes pages. Il faut avoir un processeur avec des capacités d'extension de taille de page (PSE). Cela exclut les processeurs pré-Pentium. Pratiquement tous les processeurs x86 de génération actuelle l'implémentent.
4 KiB est également une granularité de page largement répandue dans d'autres architectures. On pourrait affirmer que cette taille provient de la division d'une adresse virutale 32 bits en deux index 10 bits dans les répertoires/tables de pages et les 12 bits restants donnent la taille de page de 4 Ko.
La conception de la taille de page normale de 4Ko de l'architecture 32 bits est en fait très intéressante :)
Et j'aimerais ajouter une réponse supplémentaire pour démontrer pourquoi elle est raisonnable.
x86 utilise une "table de pages à 2 niveaux" pour convertir les adresses de mémoire virtuelle en adresses de mémoire physique.
Supposons donc que le répertoire de pages et la table des pages contiennent entrées, et la taille de la page est octets. Pour utiliser pleinement les adresse, nous avons:
Chaque entrée dans le répertoire/table de page consomme 4 octets (32 bits), donc:
Ainsi, y = 12, et la taille de la page en octets sera = = 4 Ko.
Et qu'en est-il du "tableau de pages à 1 niveau"? Ceci est intéressant car, logiquement, nous pouvons utiliser un seul tableau de pages pour la recherche d'adresse.
Supposons que le répertoire de pages contient entrées, chacune mappant une adresse à la page correspondante, et la taille de la page est octets.
Encore une fois, pour utiliser pleinement adresses, nous avons besoin de:
Et:
Nous obtenons y = 17, et la taille de la page est = = 128 Ko.
Nous pourrions également faire valoir que, dans la version "Table de pages à 2 niveaux", le répertoire de pages et la table de pages peuvent avoir des tailles différentes. Cependant, cela signifie que nous utiliserons un répertoire de pages plus grand, qui occupera plus d'une page mémoire. Malheureusement, chaque fois qu'un nouveau processus utilisateur est généré, pour son propre répertoire de pages, OS doit allouer des pages successives, ce qui n'est pas élégant par conception.
Cela dépend de l'architecture du processeur .
La taille de page par défaut est de 4 Ko sur de nombreuses architectures. Il peut généralement être augmenté (parfois beaucoup, comme les 1 Go d'AMD64) en passant en mode page énorme . Cela permet au tableau de pages d'être plus petit, ce qui peut entraîner des améliorations des performances.
Le premier processeur Intel prenant en charge la technique de mémoire virtuelle de pagination était le Intel 80386 . Le processeur prend en charge une seule taille de page, 4 Ko. Depuis sa sortie en 1985, nous devons revenir à cette période pour comprendre pourquoi Intel a choisi cette taille de page particulière.
Atlas a été le premier ordinateur à prendre en charge la pagination avec une taille de page de 3 Ko et a eu une profonde influence sur la conception de la mémoire virtuelle et la recherche connexe motivée. Le système a été conçu entre 1958-1962. Il est intéressant de noter que la taille de page prise en charge par le 80386 est quelque peu proche de la taille de page prise en charge par l'Atlas, même si le 80386 a été conçu environ 20 ans plus tard et que les ordinateurs (et les charges de travail qu'ils exécutaient) ont radicalement évolué au cours de cette période de temps! En fait, de nombreux ordinateurs de cette période utilisaient des tailles de page comprises entre 0,5 et 5 Ko. À l'époque, les chercheurs ont en fait consacré beaucoup d'efforts à l'étude des systèmes de mémoire virtuelle (pagination et segmentation).
L'une des grandes questions était: quelle est la taille de page optimale? Un grand nombre d'ouvrages ont été publiés dans les années 60 et 70 qui tentent d'étudier et de comprendre l'impact de la taille de la page sur les performances des applications et de recommander ou de fournir des directives sur la façon de choisir une taille de page. Il existe certainement un certain nombre d'articles qui n'ont jamais été publiés. Pour autant que je sache, cela inclut le document d'Intel qui dit "... Par conséquent, la taille de la page devrait être de 4 Ko." Mais les facteurs qui influencent ou interagissent avec la taille de la page et le processus de choix d'une taille de page (ou de plusieurs tailles de page d'ailleurs) sont bien connus, c'est ce dont je vais discuter dans cette réponse à un niveau de base. J'expliquerai également en particulier pourquoi une taille de page de 4 Ko est raisonnable.
Dans la méthode de pagination, la mémoire physique est organisée comme une séquence de régions de mémoire contiguës, appelées cadres de page, qui sont de la même taille (ce qui est la caractéristique qui définit la pagination1). Chaque cadre de page peut être mappé sur un bloc de taille égale d'un espace d'adressage virtuel, appelé page virtuelle.
Supposons qu'une page se compose de N
octets2 (ce qui implique qu'un cadre de page est également N
de taille par définition) et considérons un espace d'adressage virtuel qui se compose de P
pages (c'est-à-dire que les numéros de page sont {0, 1, 2 , ..., P
- 1} et le nombre total d'adresses virtuelles est N
* P
). Supposons également que l'espace d'adressage physique se compose de F
cadres de page (c'est-à-dire que les numéros de cadre de page sont {0, 1, 2, ..., F
- 1} et le nombre total de les adresses physiques sont N
* F
).
Étant donné une adresse virtuelle VA
, un mécanisme (un périphérique de mappage) est nécessaire pour déterminer l'adresse physique, PA
, à laquelle elle est mappée ou une erreur de page doit être relevé au cas où il ne serait pas mappé. Le périphérique de mappage utilise une structure de données (la table des pages) stockée quelque part pour effectuer le mappage. Il doit y avoir une entrée dans ce tableau pour chaque page virtuelle allouée qui décrit comment la page est mappée et potentiellement certains attributs supplémentaires (tels que les attributs de protection). La conception de l'entrée du tableau de pages, comme vous le verrez, interagit avec la taille de la page. Je discuterai plus tard de la conception de l'entrée du tableau des pages dans l'Intel 80386.
La taille d'une adresse virtuelle est log2(N
* P
) et la taille d'une adresse physique est log2(N
* F
). Certains bits de VA
représenteraient le décalage dans la page tandis que les autres bits représenteraient le numéro de page, qui identifie la page à l'aide du périphérique de mappage.
Combien d'options avons-nous pour la taille de la page? Eh bien, cela peut être aussi petit qu'un octet jusqu'à N
* P
ou N
* F
, le plus petit des deux. Ça fait beaucoup d'options.
Une adresse virtuelle, VA
, équivaut à une paire de numéro de page et de décalage, (PN
, OFF
). Le processus de traduction doit être aussi efficace que possible. C'est pratique pour les programmeurs3 pour que les octets d'une page soient contigus dans l'espace d'adressage. De cette manière, les adresses des éléments dans une structure de données multi-octets peuvent être calculées avec une simple arithmétique sur une seule adresse, ce qui constituerait l'adresse de base de la structure de données. Ceci peut être réalisé en utilisant le journal le moins significatif2(N
) bits (arrondis vers le haut) d'une adresse virtuelle pour représenter le décalage et le reste des bits pour représenter le numéro de page.
Si N
n'est pas une puissance de 2, certains bits seront partagés entre le décalage et le numéro de page, selon les valeurs de ces bits. En faisant de N
une puissance de 2, une telle complication n'existe pas. Il serait donc judicieux d'utiliser des tailles de page qui sont une puissance de 2. Tous les vrais processeurs qui prennent en charge la pagination utilisent des tailles de page qui sont deux (bien que l'unité d'adressabilité ne soit pas 8 bits), ce qui est logique. Mais pour être honnête, il n'est pas clair si cela importe vraiment. En utilisant la technologie d'aujourd'hui, que N
soit une puissance de 2 peut ne pas avoir d'impact mesurable sur les performances ou toute autre mesure d'intérêt. En fait, à l'avenir, car des tailles de page de plus en plus grandes sont nécessaires, il peut arriver qu'une certaine taille de page qui n'est pas une puissance de 2 soit meilleure. Mais jusqu'à présent, cela ne s'est pas produit. Le point que j'essaie de faire valoir ici est que l'option de conception de faire de la taille de la page une puissance 2 ne doit pas être automatiquement rejetée. Je pense que c'est une bonne opportunité de recherche sur les futurs systèmes de mémoire virtuelle.
Quoi qu'il en soit, en gardant à l'esprit que le choix des pages de 4 Ko a été fait dans les années 80, de telles variations extrêmement petites de la taille des pages se sont révélées (à la fois théoriques et expérimentales) avoir peu d'importance. Ainsi, la commodité des tailles de page d'une puissance de 2 a triomphé. Cela réduit le nombre de tailles de page à considérer de façon exponentielle. Mais nous avons encore une bonne gamme d'options.
Étant donné que le dispositif de mappage fonctionne au niveau des pages, l'unité d'allocation du point de vue du système d'exploitation est une page virtuelle4. Même si une application doit allouer seulement 1 octet, elle doit toujours dire au système d'exploitation d'allouer une page virtuelle entière pour cet 1 octet. Ce problème est appelé fragmentation interne. Chaque application (ou peut-être même chaque composant d'une application) possède son propre espace d'adressage virtuel à partir duquel elle alloue de la mémoire en segments de taille de page. Il est prévu que chaque application n'utilise pas une seule page pour un seul objet qu'elle alloue, mais alloue plutôt autant d'objets que possible à partir de la même page avant d'allouer plus de pages. Cependant, comme les attributs de page fonctionnent au niveau des pages, la même application peut utiliser plusieurs gestionnaires de mémoire en mode utilisateur (comme lors de l'utilisation de plusieurs runtimes C/C++), et il est difficile pour l'application de partager des parties des pages qu'elle n'utilise pas avec d'autres applications, une fragmentation interne peut se produire dans de nombreuses pages du système. L'utilisation de tailles de page plus petites peut aider à réduire la quantité de mémoire physique (pour l'ensemble du système) et virtuelle (par processus) gaspillée.
De plus, les applications passent généralement par un certain nombre de phases tout au long de leur durée de vie, où elles présentent des besoins en mémoire différents selon les phases. Si la taille de la page est, disons, de 16 Ko, mais que de nombreuses applications peuvent nécessiter seulement moins de 10 Ko pour la plupart de leurs phases, il y aurait alors beaucoup de mémoire physique gaspillée, ce qui pourrait conduire à des situations de mémoire insuffisante qui pourraient avoir a été évitée si des tailles de page plus petites, telles que 8 ou 4 Ko, étaient prises en charge.
Les tailles de page plus petites sont préférables pour gérer les erreurs de page logicielle de copie sur écriture, car plus la page est petite, plus la création de la copie prendrait moins de temps. Pour des tailles de page extrêmement petites, cela peut ne pas faire de différence mesurable, selon la bande passante du bus mémoire.
Les quantités typiques de mémoire physique disponibles dans les ordinateurs dans les années 70 se situaient entre 10 et 100 s de Ko. Il ne serait pas logique d'avoir des pages de centaines de Ko ou plus. En fait, les ensembles d'applications de travail à l'époque n'étaient généralement que de quelques dizaines ou dizaines de Ko. Il est donc peu probable que même des tailles de page aussi petites que 16 Ko soient pratiques, car seules quelques pages peuvent consommer toute la mémoire physique disponible. La taille de la page doit être cohérente avec la quantité de mémoire physique. Cet argument peut être appliqué aux systèmes d'aujourd'hui bien sûr (cela n'aurait pas de sens d'avoir des pages de 128 Go par exemple).
Donc, compte tenu des tailles des ensembles de travail et de la disponibilité de la mémoire physique des années 70 et début des années 8 , la taille de la page devrait être une puissance de 2 dans la plage 2-214. Cool, nous avons maintenant seulement 15 options à choisir.
Nous pouvons également affirmer que de plus grandes tailles de page sont meilleures. Pour le même jeu de travail, des tailles de page plus petites impliquent un plus grand nombre de pages par application, ce qui nécessiterait des entrées de table de pages pour activer la traduction. Cela nécessite fondamentalement des tables de pages plus grandes, quelle que soit la structure des tables de pages (bien que la surcharge exacte dépende de la conception de l'entrée de table de pages elle-même, dont je parlerai plus tard). Imaginez avoir par exemple des pages de 4 octets et des ensembles de travail typiques de dizaines de Ko. Ensuite, la plus grande partie de la mémoire physique serait réellement allouée pour contenir les tables de pages, pas les données. La pagination des tables de pages pour le stockage de seconde génération entraîne des erreurs de double page pour les références de mémoire individuelles, ce qui serait absolument terrible pour les performances. Une telle conception est évidemment ridicule.
Essentiellement, la taille de la page ne doit pas être (beaucoup) plus petite que la plus petite taille possible du jeu de travail qui puisse éventuellement l'être. Cela exclut immédiatement les pages de tailles 2-26, nous laissant 8 options. Les articles des années 70 et du début des années 80 qui étudient la taille des pages étudient principalement ces 8 options.
Il y a une autre raison qui rend les pages de plus grande taille avantageuses. L'un des avantages de la mémoire virtuelle est de pouvoir utiliser de manière transparente le stockage secondaire en plus de la mémoire principale pour stocker des données volatiles. Cependant, les périphériques de stockage secondaires sont mécaniques et fonctionnent mieux avec des transferts en masse. Il s'agit vraiment d'une directive et nous ne devons pas encore exclure la taille des pages. Il existe des appareils avec des conceptions et des caractéristiques différentes et, à terme, l'avantage de performance des transferts en masse saturera à un moment donné. Mais c'est certainement quelque chose à prendre en compte lors de la mesure de l'impact des tailles de page sur les performances. Si le type d'applications envisagées présente peu de localité spatiale, alors des tailles de page plus petites seraient toujours préférables car la copie d'octets supplémentaires vers ou depuis le disque n'est pas exactement gratuite.
La localité de référence spatiale encourage l'utilisation de certaines tailles de page. Pour les très petites tailles de page, il est très probable que tous les octets de la page soient utilisés dans un court laps de temps. À mesure que la taille d'une page augmente, le nombre d'octets moins susceptibles d'être utilisés augmente. Cependant, pour les très grandes pages, l'ensemble du jeu de travail peut tenir dans un petit nombre de pages, quelle que soit la localité. Par conséquent, pour minimiser le nombre de défauts de page, la taille de la page doit être soit trop petite, soit trop grande, mais pas entre les deux. Mais finalement, cela varie d'une application à l'autre. Les paradigmes de programmation émergents, tels que la programmation orientée objet et la programmation fonctionnelle, et les techniques telles que le multithreading peuvent en fait réduire la localité spatiale en raison de l'utilisation extensive de structures liées et en raison de la façon dont différentes applications interagissent les unes avec les autres. Des tailles de page plus grandes sont préférables pour réduire le nombre de défauts de page. Cependant, des tailles de page plus petites peuvent être meilleures pour la mémoire partagée entre plusieurs applications afin de réduire la fragmentation interne des pages partagées. Il a également été démontré expérimentalement que le nombre de cadres de page pouvant être conservés dans la mémoire principale est corrélé avec le nombre de défauts de page, favorisant des tailles de page plus petites.
Le besoin de TLB était bien reconnu à cette époque. Intel les a appelés page caches dans leurs brevets (je ne sais pas si Intel a été le premier à utiliser ce terme). Les TLB rapides sont très importants car la traduction d'adresse est sur le chemin critique de l'exécution des instructions. Pour les rendre aussi rapides que possible, ils doivent être minuscules, mais ils ne peuvent alors mettre en cache qu'un petit nombre d'entrées de table de pages. Cela motive l'utilisation de pages de plus grande taille.
Dans la recherche de la taille de page optimale, il s'avère qu'il n'y en a pas. On savait à l'époque qu'il fallait prendre en charge plusieurs tailles de page. En fait, le système Multics conçu en 1965 supportait des pages de 64 ou 1 024 mots (un mot a une taille de 36 bits). Tailles de page dans la plage 27-214 se sont avérés optimaux à la fois empiriquement et théoriquement dans différents scénarios. Intel doit avoir observé que les pages de 4 Ko donnent les meilleures performances moyennes pour les applications que leurs clients utilisaient dans les années 80. Pour les ordinateurs et applications d'aujourd'hui, de si petites différences de taille de page ne font pas beaucoup de différence comme c'était le cas dans les années 70 et 80.
La conception de l'entrée du répertoire de pages et de la table des pages est discutée en détail dans un Intel brevet . Ceci est important car la taille de l'entrée du tableau des pages et la structure globale du tableau des pages ont été prises en compte dans de nombreuses études sur la taille des pages car elles interagissent toutes les unes avec les autres. Je préfère ne pas en discuter plus en détail pour garder la réponse courte.
Intel a obtenu un brevet il y a quelques mois qui propose apparemment un système avec une taille de page par défaut de 64 Ko, mais en même temps prenant en charge des pages de 4 Ko (et d'autres tailles de page IA-32e) pour une compatibilité descendante. Je cite le brevet:
En raison de la prise en charge du mappage de la page de 64 Ko en sous-pages de 4 Ko, VA64 prend directement en charge toutes les opérations actuellement définies sur les pages de 4 Ko, y compris les bits de protection indépendants par page de 4 Ko et les mappages d'adresse alignés sur 4 Ko. VA64 prend également en charge la gestion des pages du noyau du système d'exploitation sur des limites de 4 Ko, même lorsque le noyau du système d'exploitation alloue de la mémoire en unités de 64 Ko. En raison de la prise en charge de grandes pages, VA64 prend en charge toutes les divisions de la plage d'adresses virtuelles en pages prises en charge par un système de pagination existant tel que le système de pagination IA-32e d'Intel Corporation. Par conséquent, VA64 prend en charge les applications et les périphériques matériels qui fonctionnent avec un noyau de système d'exploitation Windows® de 4 Ko, tout en tirant pleinement parti des pages de 64 Ko lorsque des pages de 64 Ko peuvent être utilisées.
Les capacités de VA64 peuvent être adoptées progressivement par le noyau du système d'exploitation, plutôt que de les obliger toutes à être prises en charge dans le noyau du système d'exploitation compatible VA64 de première génération. Par exemple, un noyau de système d'exploitation compatible VA64 pourrait commencer par mapper toutes les pages aux tailles actuelles (par exemple, 4 Ko/2 Go/1 TB dans le système de pagination IA-32e d'Intel Corporation), mais en changeant à un nouveau format de table de pages. Après le changement de format de table de pages, le noyau du système d'exploitation pourrait être modifié pour mapper la mémoire virtuelle en unités de 64 Ko et changer pour stocker des pages de 64 Ko dans sa liste libre. Ensuite, le noyau du système d'exploitation pourrait commencer à utiliser 64 Ko pages chaque fois que l'alignement et les protections le permettent, et ajouter la prise en charge d'autres capacités VA64.
Je ne sais rien d'autre sur le système de pagination VA64 autre que ce qui est écrit dans le brevet. Il n'y a rien là-dessus sur Internet. Je suppose que nous en saurons plus bientôt.
Denning, P.J. (1970). Mémoire virtuelle . ACM Computing Surveys Volume 2 Numéro 3, 153-189.
Gelenbe, E., Tiberio, P., et Boekhorst, J.C. A. (1973). Taille de la page dans les systèmes de pagination de la demande . Acta Informatica, 3 (1), 1-23.
Alanko, T.O., et Verkamo, A. I. (1983). Segmentation, pagination et tailles de page optimales dans la mémoire virtuelle . Évaluation du rendement, 3 (1), 13-33.
Corbató, F. J. et Vyssotsky, V. A. (1965). Introduction et aperçu du système Multics . Dans Actes du 30 novembre au 1er décembre 1965, conférence informatique conjointe d'automne, partie I (pp. 185-196).
(1) En fait, la taille d'une seule page virtuelle peut être multiple de la taille d'un cadre de page, mais n'y allons pas.
(2) Nous pouvons généraliser la formulation et utiliser le terme "mot" pour désigner la plus petite unité de mémoire adressable plutôt que l'octet, mais ce n'est pas important ici.
(3) Peut-être pas des programmeurs, selon le langage de programmation, mais des compilateurs, des éditeurs de liens, des assembleurs et des outils qui fonctionnent avec du code binaire.
(4) Il est certainement possible de concevoir un système qui prend en charge l'utilisation de la pagination et de la non-pagination en même temps, prenant ainsi potentiellement en charge plusieurs unités d'allocation, mais n'y allons pas.
Je l'ai obtenu de l'article de wikipedia et je cite:
La taille de la page est généralement déterminée par l'architecture du processeur
Consultez l'article ci-dessous:
J'ajoute cette réponse/commentaire car le calcul de sleepsort est très intéressant, je dois l'ajouter à ma page web (en mentionnant bien sûr la source). Une réponse (possible) à la question de savoir comment calculer la taille des pages par programme peut être trouvée ici . La façon dont il est calculé comme mentionné par sleepsort est très intéressante. J'ai fait la même chose pour x86_64 et le résultat n'était pas ce à quoi je m'attendais. Cependant, en lisant plus loin gestion de la mémoire x86_64 j'ai trouvé que pour 64 bits Intel, 16 bits ne sont pas utilisés, laissez-nous 48 bits pour calculer. 9 bits pour les branches de l'arbre mémoire, chaque branche encore 9 bits, ici dans 9 autres pour les branches et enfin 9 bits pour les feuilles de la dernière branche. Donc 48 - 36 = 12 bits pour chaque adresse de la page mémoire. 2 ^ 12 = 4096 comme mentionné précédemment par sleepsort. Je me demande simplement combien de personnes passent cette architecture, 3 ou 4 (si quelqu'un peut expliquer cela) après le calcul de sleepsort:
2^x * 2^x * 2^x * 2^x * 2^y = 2^48
4x + y = 48
this time we have 8 bytes for each address (8 bytes * 8 bits / byte = 64 bits)
2^y / 2^3 = 2^x
y - 3 = x
filled in in previous equation:
4(y - 3) + y = 48
4y - 12 + y = 48
5y = 60
y = 12
because 2^y represents the pagesize, the size = 2^12 = 4096 bytes
Laissez-moi la question "et ces énormes pages sous Linux"?