Existe-t-il des alternatives au modèle de pile + tas + mémoire statique?


9

Tous les programmes que j'ai vus organisent leur mémoire de données en une ou plusieurs piles d'appels (généralement de taille fixe, mais parfois pas), le tas et la mémoire statique. Dernièrement, le stockage statique local des threads a également été ajouté à cela.

Y a-t-il eu des tentatives pour organiser la disposition de la mémoire de données d'une manière radicalement différente, par exemple sans la pile d'appels? Ou organiser la mémoire d'une manière différente qui accomplit la même chose?


Cela dépend de ce que vous entendez par "pile". Vous pouvez placer les cadres de la pile d'appels dans le tas (les lier avec des pointeurs). Ensuite, vous n'avez pas de région de mémoire linéaire dédiée pour la pile, mais conceptuellement, vous avez toujours une pile d'appels.

et dépend de ce que vous entendez par "récemment". Je pense que le stockage local des threads est aussi ancien que les threads. Mais auparavant, il était accessible via les appels système, alors que maintenant les langues plus récentes vous permettent d'y accéder directement.
DXM

La pile d'appels est nécessaire car les fonctions procédurales doivent savoir qui les a appelées afin de pouvoir retourner des résultats et poursuivre l'exécution. Le mécanisme actuel si cela est en fait assez bon marché en termes de cycles CPU et avec x64 au moins, presque tous les arguments de fonction sont passés par des registres
James

2
Vous pouvez trouver le post d'Eric Lippert, Why Have a Stack? d'intérêt. Son principal argument est qu'une pile fournit un moyen simple et efficace de suivre les emplacements de mémoire. Il discute d'une alternative dans plusieurs articles beaucoup plus anciens, Continuation Passing Style .
Brian

Réponses:


8

Vous voudrez peut-être prendre du recul et voir d'où et pourquoi ces modèles existants viennent. Lorsqu'un processus est créé, on lui donne simplement une zone de stockage plate qui est simplement indexée de 0 à N. Parce que cette zone de stockage (en parlant de RAM ici) est soutenue par un matériel dédié et certains semi-conducteurs de fantaisie, il se trouve être assez rapide, mais ce n'est pas le seul du genre. D'autres appareils tels que les disques durs sont essentiellement la même chose, l'espace plat adressable par un index, mais beaucoup plus lent.

La raison pour laquelle "un tas" existe est qu'il serait impossible pour chaque application de tenter de gérer seule l'utilisation de la RAM. Il y a longtemps, c'est exactement comme cela que les choses se sont passées, les programmeurs ont planifié à l'avance exactement à quoi chaque emplacement de RAM serait utilisé. Comme le logiciel est devenu plus complexe, quelqu'un l'a dit, ne serait-ce pas bien si je pouvais simplement aller dans une boîte noire et dire "J'ai besoin de 10 octets alors donnez-moi" et ne pas avoir à vous soucier de tous les détails complexes de l'endroit et de la façon dont ces 10 octets proviennent ou comment ils sont récupérés. C'est ce qu'est un tas, n'est pas vraiment plus basique que ça.

Chaque fois qu'un thread est créé, il existe des structures de données (et une pile), qui sont acquises en utilisant la même "opération gimme" que je viens de décrire. Une pile à peu près universellement utilisée car elle s'adapte parfaitement aux cadres de pile d'appels de fonctions et à leur nature LIFO. En théorie, chaque invocation de fonction et variables locales pourraient être allouées sur le tas, mais cela serait tout simplement trop cher, par rapport à quelques instructions d'assemblage nécessaires pour mettre à jour le registre du pointeur de pile (ESP sur x86).

Le stockage local de threads (TLS) est également construit sur le dessus du tas. Lorsqu'un thread est créé, dans le cadre d'un déplacement vers le segment de mémoire pour allouer de la mémoire aux structures de gestion, un espace distinct pour TLS est également alloué à partir du segment de mémoire.

Donc à la fin, tout ce que vous avez vraiment est un allocateur de mémoire générique (c'est-à-dire le tas) et tout le reste est une forme spécialisée en plus de cela. En d'autres termes, si vous êtes prêt à renoncer à un aspect de "Je veux allouer autant (ou aussi peu) que je veux, gardez-le aussi longtemps que je veux et gratuit quand je veux", vous pourriez vous en sortir off allocateur de tas générique pour un autre modèle qui offre de la vitesse mais au prix d'une autre limitation.

Prenez la pile. Il est incroyablement rapide par rapport au tas, mais les deux compromis sont 1) vous ne contrôlez pas quand la mémoire est libérée; au lieu de cela, une fois la fonction terminée, tout ce que vous avez alloué est parti et 2) parce que les piles sont généralement de taille limitée, vous devez faire attention d'allouer de grandes quantités de données directement sur la pile.

Un autre type de «modèle de mémoire» est le Virtual Memory Manager (VMM) offert par à peu près tous les principaux systèmes d'exploitation via des appels système. VMM est très similaire au tas dans le sens où vous pouvez demander n'importe quelle quantité de mémoire et la conserver aussi longtemps que vous le souhaitez. Cependant, la limitation est que vous ne pouvez allouer de la mémoire que par multiples de taille de page (par exemple, 4 Ko), donc l'utilisation directe de VMM entraînerait une surcharge importante dans une application typique qui alloue souvent 8 à 24 octets à la fois. En fait, à peu près chaque implémentation de tas est construite au-dessus de VMM spécifiquement pour permettre une allocation très générique, non spécialisée et en petits blocs. Heap va à VMM chaque fois qu'il a besoin de plus de mémoire, puis distribue de nombreux petits morceaux de cette mémoire à l'application.

Si vous avez une application, qui a besoin d'allouer de gros blocs, vous pouvez envisager d'aller directement à VMM, bien que certains tas aient une instruction if à l'intérieur de malloc () et si la taille du bloc est supérieure à un certain seuil, ils vont simplement à VMM pour vous.

Une autre forme d'allocateurs au lieu d'utiliser directement le tas, serait les pools. Un pool est un allocateur spécialisé où tous les blocs sont de la même taille. Les pools (tout comme la pile et TLS) sont construits sur le tas ou VMM. Les piscines sont utiles dans les endroits où vous allouez beaucoup (des millions) de petits objets éphémères de même taille. Imaginez un service réseau traitant les demandes entrantes. Chaque demande client peut entraîner l'allocation de la même structure à N octets pour traiter cette demande. Le compromis avec l'utilisation des pools est que chaque pool ne gère qu'une seule taille de bloc (mais vous pouvez créer plusieurs pools). L'avantage des pools est que, comme tous les objets sont de la même taille, ils ne nécessitent pas de logique complexe. Au lieu de cela, chaque fois que vous avez besoin d'un nouveau bloc, il vous donne simplement celui qui a été récemment libéré.

Et enfin, souvenez-vous de cette chose sur le disque dur que j'ai mentionnée en haut. Vous pouvez avoir un modèle de mémoire qui se comporte comme un système de fichiers et reproduit la même idée d'entrées de répertoire et de nœuds i pour vous permettre une allocation hiérarchique des blocs de données où chaque bloc de données est adressé avec un chemin. C'est exactement ce que fait tmpfs .

Au-delà des choses que j'ai mentionnées, je suis sûr qu'il existe d'autres modèles plus spécialisés, mais à la fin, car tout est basé sur un espace d'adressage plat (c'est-à-dire jusqu'à ce que certains génies proposent une sorte d'espace non-bizarre-un $$ non plat ), tout revient à cet allocateur générique "gimme" qui est soit VMM soit le tas.


1

Les seuls cas auxquels je peux penser sont dans le matériel spécialisé où tout peut fonctionner dans des emplacements fixes en mémoire. Presque tout dans le modèle de mémoire actuel est requis si vous voulez des programmes entièrement flexibles.

Sans la pile, vous ne pouvez pas avoir de variables locales, de piles d'appels, etc. Tout ce que vous écrivez pour implémenter finira par ressembler beaucoup à la pile.

La mémoire statique et le tas que vous pourriez potentiellement supprimer pour certaines applications, mais encore une fois, vous en aurez besoin sous une forme ou une autre pour faire quelque chose de plus avancé.

Donc, tout ce que vous inventez pour remplacer l'un de ces trois finira par ressembler beaucoup à l'un de ces trois ...

Pour l'aborder sous un autre angle, que pourriez-vous ajouter de nouveau? Vous pourriez potentiellement argumenter que des éléments comme les processeurs graphiques / physiques / les caches de processeur / etc sont un nouvel emplacement de mémoire, mais en réalité ils ne sont qu'une instance distincte ou un moyen d'accélérer l'accès aux modèles existants.

... donc jusqu'à ce que quelqu'un fasse un énorme saut conceptuel, je pense que nous ne verrons probablement pas de changements majeurs dans ce domaine pendant longtemps ...


4
La plupart des gens ont tendance à supposer que la voie actuelle est la meilleure / seule voie, et si on leur donne une liste vierge, il suffit de copier ce qui existe déjà. Les autres personnes sont celles qui font réellement avancer le progrès technologique. Cela ne veut pas dire que je connais personnellement des modèles concurrents sérieux (à moins de compter les ordinateurs quantiques), mais affirmer que tout ce que l'on pourrait trouver ressemblerait à ce qui existe déjà est essentiellement une forme de raisonnement circulaire.
Aaronaught

@Aaronaught: le revers de votre argument est que d' autres personnes passent des tonnes de temps, d'argent et d'énergie à sortir des sentiers battus et pour 1000 (peut-être beaucoup plus) d'entre elles, on pourrait éventuellement faire progresser le progrès technologique, tandis que les autres n'iraient nulle part . Alors que le premier groupe, que l'on pourrait considérer comme plus pratique, prend ces modèles existants tels quels et innove par-dessus eux :)
DXM

@aaronaught Je pense que j'ai couvert cela avec "donc jusqu'à ce que quelqu'un arrive avec un bond conceptuel géant en quelque sorte";) Si vous avez un meilleur modèle alternatif, n'hésitez pas à le suggérer ... sinon cela semble un peu hypocrite de se plaindre "certaines personnes" quand vous êtes l'un d'entre eux :)
Tim B

1
@DXM: Alors? Ai-je dit que nous devrions tous investir notre temps dans la recherche de nouveaux modèles de mémoire? Je ne faisais que souligner la faille (importante) dans l'affirmation selon laquelle une personne ne peut inventer que des choses qui ont déjà été inventées.
Aaronaught

Une réclamation que je n'ai jamais faite ...
Tim B
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.