La RAM non volatile
La prochaine révolution du soft viendra du hard!
Par Philippe PRADOS - 2018
www.prados.fr

Nous sommes à l'aube d'une nouvelle révolution informatique. Bientôt, nos programmes ne seront plus comme avant, grâce à une nouvelle technologie : les RAM persistantes ou NVRAM pour Non-Volatile-RAM[1].

Dans peu de temps, il sera possible d'acheter de la RAM qui n'a pas besoin d'être alimentée pour maintenir les informations ! Et cela avec une latence de deux à quatre fois la latence de la RAM classique (pour le moment) et plusieurs Giga/s de throughput.

Seul inconvénient : l’endurance. L’endurance est un nouvel élément à prendre en compte dans les algorithmes. Cela fait référence au nombre limité d’écritures par case mémoire. Comme pour les mémoires de masse SSD, ces nouvelles RAM sont généralement limitées en nombre d’écritures sur chaque adresse
Ces mémoires peuvent être considérées comme des remplacements de la RAM classique eut égard à leur faible consommation électrique et à leur densité de mémoire par cm².

Pour produire les NVRAM, de nombreuses technologies émergent (FeRAM MRAM STT-RAM, RRAM), avec des performances variables.
Intel vient d’annoncer la sortie du SSD Optane DC P4800X qui utilise la nouvelle RAM 3D XPoint. L’entreprise prévoir des barrettes pour le deuxième trimestre de 2018. L'objectif est de concevoir une mémoire flash NAND 1000 fois plus rapide, 1000 fois plus endurante et 10 fois plus dense que celles utilisées dans les SSD actuels, avec des blocs de la taille d’un mot (64 bits). Les débits atteignent actuellement 2400 Mo/s en lecture et 2000 Mo/s en écriture. Rapidement, des volumes de plusieurs To seront disponibles (4 To annoncé). Ce sont des NVDIMM type F.
D'autres approches consistent à associer de la RAM classique avec de grosses batteries et un backup sur SSD. Lors de la perte d’électricité, les batteries sont suffisantes pour sauvegarder la RAM sur le SSD. À la reprise du courant, l’opération inverse est appliquée. Ce sont des NVDIMM type N.
Nous aurons de plus en plus de RAM disponible. Par exemple, la machine Jaguar (3e du top 500) du Oak Ridge National Laboratory, consomme 200 TB de mémoire (2GB/Core).
Qu'est ce que cela change ? Et bien cela ouvre la porte à de très nombreuses améliorations. Avant de les survoler, il faut bien comprendre comment cela fonctionne.
Qu'est-ce ?
Nos processeurs permettent d’adresser jusqu'à plusieurs téra-octets de mémoire vive. Les OS proposent dors et déjà de partager de la mémoire entre différents processus et même d’utiliser cette mémoire comme cache pour la mémoire morte. Le composant matériel nommé MMU permet de sécuriser ce partage de ressource, et établit une table de correspondance entre les adresses en mémoire physique et les adresses utilisées par les programmes, dites virtuelles.

L’utilisation des NVRAM exploite cette abstraction. Via un driver, il va être possible de demander un espace mémoire non volatile. Cette mémoire à la particularité de garder son état, même en cas de coupure brutale de courant. La technologie garantit qu'il n'est pas possible d'avoir une modification partielle d’un word (64 bits). Donc, les programmes peuvent stocker des structures complexes dans cette mémoire et les retrouver instantanément même si la mémoire n’a pas été alimentée électriquement de manière continue.
Pour bénéficier de ce modèle, il est préférable qu’un processus puisse mapper la NVRAM à la même adresse mémoire après un reboot. Sinon, les compilateurs et frameworks doivent calculer les adresses mémoires à partir d’une base, changeant à chaque reboot.
Le noyau Linux 10 et suivant permet ces deux modèles d'accès. Il suffit d’indiquer une tranche d’adresse de mémoire à réserver à cet usage, dans un paramètre du boot de l’OS. On trouve les types d’approches dans les librairies : adresse classique, ou adresse calculée à partir d’une base variable.
Contraintes techniques
Dans les faits, c'est un peu plus compliqué. En effet, il faut s'assurer, lors du développement de l'application, qu'à aucun moment, en cas d'interruption du programme ou de la machine, la mémoire ainsi modifiée ne se retrouve dans un état incohérent (modification partielle, pointeur dans le vide, etc). Sauf à resetter volontairement cette mémoire, une structure mal construite le restera même après un redémarrage.
Cela nécessite un modèle de développement assez similaire aux codes présents dans les cartes bancaires qui doivent résister à l'arrachage des cartes.
Il faut donc travailler dans un mode « transaction en mémoire » (STM – Software Transaction in Memory). C'est-à-dire que le programme doit apporter des modifications dans des zones temporaires identifiées, et valider les modifications en écrivant qu'un seul pointeur ou entier. Il faut s’appuyer sur les opérations atomiques de la mémoire (l’écriture de 64 bits), pour valider une transaction dans une structure mémoire.
Après un reboot physique, lors de la reprise de l’alimentation, si une transaction n’a pas été validée, le code doit faire le ménage sur les modifications partielles en cours.
Attention, une instruction d’écriture de 64 bits, vu du processeur, n'est pas toujours équivalente à l'écriture physique en RAM ou en NVRAM. L’écriture ne s’effectue que dans les caches du processeur, avant d’être éventuellement déposée dans la RAM. Il ne faut pas oublier de demander la purge des caches du processeur pour que la valeur soit réellement écrite dans la NVRAM. De nouvelles instructions sont présentes dans les processeurs Intels pour accompagner cette évolution. CLWB et PCOMMIT permettent de flusher les données des caches des processeurs dans la RAM physique, sans invalider la ligne de cache. (Attention, le choix des instructions est encore instable).
En quoi cela va révolutionner nos applications ? Imaginons plusieurs scénarios d'usages qui ne tarderont pas à apparaître.
Allocation mémoire
Un des modèles d’allocation de PMem d'Intel permet de remplacer automatiquement les allocations mémoires classiques en RAM (malloc(), free() ) pour utiliser la mémoire persistante. Cela permet d’avoir potentiellement l’équivalent de plusieurs tera-octets de RAM en ligne. L’objectif n’est pas d’exploiter la capacité de cette mémoire à résister à un crash, mais d’augmenter la mémoire disponible à l’aide d’une mémoire de masse de type NVDIMM. En cas de coupure brutale de courant, la mémoire est abandonnée. La mémoire persistante est utilisé pour son prix et non pour sa capacité à persister les informations. Des travaux conjoint entre Intel et Sylladb indique un TCO de 50% par rapport à une approche intégralement en RAM classique.
Pour bénéficier de la persistance de cette mémoire, un allocateur doit garantir l’absence de fuite, même en cas d’interruption électrique. Différents travaux de recherche proposent des allocateurs spécialisés pour ces mémoires.
PMem propose un modèle permettant d’avoir un allocateur mémoire transactionnel. En cas de coupure de courant pendant l’allocation ou la libération d’un pointeur, l’algorithme est en capacité de rétablir la situation, en annulant les étapes transitoires.
Les spécificités techniques de ces nouvelles RAM nécessitent de revoir les algorithmes afin de respecter les spécificités suivantes :
- Les écritures sont plus lentes que les lectures
- L’endurance de la mémoire en écriture est limitée
Des émulations de NVRAM permettent de tester les impacts de cette dissymétrie des temps d’accès, en ajoutant artificiellement de la latence.
Plusieurs approches sont recommandées :
- ne pas hésiter à relire des données pour éviter des écritures (par exemple, pour éviter un tri des données pour une recherche future plus rapide, il est préférable de parcourir linéairement des données non triées. Cela réduit le nombre d’écriture. C’est l’approche utilisée par de nouveaux algorithmes de B-Tree)
- utiliser la RAM classique comme cache, pour référencer rapidement les données en RAM persistante et réduire les écritures
- gérer le recyclage de la mémoire pour éviter de surcharger certaines zones (approche LIFO à la place de FIFO)
L’approche WAlloc consiste à concevoir un système d’allocation basé sur ces nouvelles mémoires, avec pour objectif de réduire le nombre d’écriture des méta-données (les tailles des zones libres, la dernière date d’utilisation d’une zone, etc.) et de contrôler l’utilisation de la mémoire pour éviter d’utiliser toujours les mêmes zones, au risque de la vieillir prématurément. Une partie des méta-données est en RAM classique. Après un crash, il est possible de les reconstruire.
Nous constatons que cela est assez éloigné des approches des algorithmes actuels de ramasse-miettes. De plus, ces algorithmes ont de grandes difficultés à gérer de gros volumes de mémoire. Dans une optique : extension de la RAM classique, on peut imaginer un GC (Garbage Collector) à deux niveaux. Les données chaudes sont en RAM classique. Un LRU (Least Recently Used) déplace progressivement les données en NVRAM, au fur et à mesure de leurs résistances au GC. Un GC Spécifique se contente d’identifier les espaces mémoires à libérer, en évitant, autant que possible, de déplacer les objets, afin d’améliorer l’endurance.
Mais cette approche ne permet pas de bénéficier de la rémanence des données après un arrêt du programme. Il est nécessaire de pouvoir indiquer un allocateur spécifique dans les langages de développement, pour permettre de sélectionner l’espace mémoire à utiliser.
Par exemple, en C++, il est possible de définir un opérateur new() à cet usage.
Allocation en mode bloc
Il est possible d’utiliser la NVRAM pour émuler un device en mode bloc. Comme cette technologie garantit l'écriture cohérente d'un WORD (64 bits), il est possible d'avoir un bloc ou secteur d’un fichier qui est partiellement écrit lors d’un crash. (La technologie SSD garantit l'atomicité des écritures sur un bloc). Pour éviter cela, les drivers proposent d'écrire la nouvelle version du bloc dans une nouvelle zone mémoire avant d'invalider le bloc référencé précédemment. Avec cette stratégie, il est possible d'utiliser les NVRAM comme un disque SSD, avec garantie de la cohérence du bloc dans son ensemble.
C’est une approche simple pour exploiter cette ressource comme un disque type SSD, mais plus rapide.
Des approches plus inclusives proposent de nouveaux gestionnaires de fichiers, dédiés aux NVRAM. Une première idée est de gérer les structures arborescentes des répertoires et des inodes en NVRAM, et les données elles-mêmes en mémoire de masse classique.
BPFS propose un gestionnaire de fichiers, optimisé pour éviter la duplication de bloc, en privilégiant la modification “sur place” lorsque cela est possible.
Intel propose également une implémentation PMFS, qui permet d’améliorer notablement les performances par rapport à une approche classique, orienté “secteur”, prévu pour une mémoire de masse lente.
Transaction en mémoire

Le code doit travailler dans des transactions s’effectuant en mémoire. Par exemple, une implémentation consiste à indiquer par avance les zones mémoires qui seront modifiées. Elles sont alors copiées et mises de côté. Puis l’algorithme applique les modifications sur place. Si tout se passe correctement, les données copiées sont abandonnées. Sinon, elles peuvent servir à restituer la mémoire dans son état d’origine. Cela permet d’annuler la transaction en cours.
Une autre stratégie est proposée par Microsoft. Elle consiste à disposer de deux espaces mémoires identiques. Les modifications sont effectuées dans l’une d’elle, sur place, sans devoir auparavant copier les données. Un verrou est alors posé pour informer que les données n’ont pas encore été dupliquées dans l’autre espace. Puis, en tâche de fond, les copies sont réalisées dans le deuxième espace. Si une modification est nécessaire dans la zone mémoire verrouillée, il faut attendre le déverrouillage de cette zone. L’idée est d’effectuer les copies après les modifications, après le commit, en tâche de fond, avant de libérer les verrous. Pour cela, une duplication “intégrale” de la mémoire est gérée en tâche de fond.
A noter que des solutions hardware sont à l’étude, pour gérer les transactions en mémoire.
Quelque soit la solution retenue, le coût supplémentaire nécessaire aux algorithmes à la copie de zone mémoire et à l’invalidation des caches des processeurs impacte les performances.
Il est donc préférable d’utiliser les spécificités des données manipulées pour permettre un “commit” des modifications par l’écriture d’un seul pointeur (pointer flip) ou d’un long. Par exemple, un gestionnaire de fichier peut ajouter des données à la fin du dernier bloc, et le valider en modifiant la taille du fichier (écriture d’un long). En cas de crash avant l’ajustement de la taille, les données ajoutées seront toujours présentes, mais considérées comme absentes du fichier, car la taille n’est pas encore modifiée.
La programmation fonctionnelle est un bon candidat pour un modèle Software Transaction in Memory (STM). Elles se basent sur un modèle de développement où les objets n'évoluent plus une fois construits. Les algorithmes construisent de nouveaux objets pour chaque modification, en cherchant au maximum à mutualiser les objets déjà présents. En cas de crash, il suffit de supprimer les objets en cours de construction pour rétablir un état stable. L’impact négatif de cette approche est le débit de création des objets, nécessaire à chaque modification.
Pour les langages utilisant des mutations d'objets “sur place”, il va falloir travailler plus en profondeur pour être compatible avec ce modèle de développement.
Pour tenir compte de ces spécificités, de nouveaux algorithmes sont proposés pour les structures classiques comme les hash-tables, avec pour ambition de mieux gérer les collisions afin de réduire les écritures mémoires, en évitant de devoir trier ou déplacer des données (via l’utilisation de deux algorithmes de calcul de hash). Des structures combinant les deux types de RAM sont utilisées. Les données fortement volatiles sont en RAM classique. Les autres données sont en NVRAM. Pour optimiser l’utilisation des caches des processeurs, l’utilisation d’un dictionnaire de valeurs pour les clés à tailles variables est également une stratégie payante. Ainsi, il est possible de co-localiser les structures et les valeurs.
De nouveaux algorithmes pour des BTree persistants sont également proposés. Ils peuvent être utilisés pour les index all-in-memory des bases de données SQL.
Partage de NVRAM entre nœuds
Il est également possible d'imaginer de partager les NVRAM de différents serveurs. Des membres d'un cluster classique se partagent l'espace d'adressage des différents processeurs (264), en s’arrangeant pour utiliser les mêmes adresses virtuelles. Par exemple, le premier node utilise l’espace de 0X1000M à 0x1FFFFM. Le suivant, de 0x2000M à 0x2FFFM et ainsi de suite. Chaque nœud est autorisé à allouer des objets et à les modifier dans sa zone mémoire réservée. Les modifications sont broadcastées vers les autres membres du cluster pour mise à jour et lecture. Par exemple, lorsqu’un serveur modifie des données dans l’espace 0x2000M à 0x2FFFM, ces modifications sont propagées vers les autres nodes. Ainsi, chacun obtient une visibilité de l'intégralité de cette mémoire distribuée qui devient partagée entre les nœuds (à la latence près).
Constatant qu’avec un réseau Infiniband, il est plus rapide d’interroger le serveur voisin pour lui demander des données dans son cache mémoire (centaine de nanosecondes), que de consulter le disque local (plusieurs milliseconds) ou un disque SSD (une douzaine de microseconde), des solutions proposent déjà de partager de la mémoire entre nodes.
Paramétrage et initialisation
Un cas d’utilisation consiste à mémoriser dans cette mémoire spéciale toutes les structures généralement calculées lors de l'initialisation d'une application. Pourquoi lire des fichiers, les interpréter, les convertir en entier ou en flottant, construire des listes ou des tables de hash, à chaque fois qu'une application démarre ? Il est bien plus efficace de ne faire cela qu'une seule fois, et d'exploiter les structures ainsi construites directement depuis la NVRAM. Les programmes pourront ainsi démarrer bien plus rapidement. La configuration est en NVRAM.

Demain, on ne livrera pas des fichiers de configuration mais des images mémoires pré-construites. Une interface utilisateur ou une API se charge de proposer le moyen de modifier les paramètres directement en mémoire.
Cette mémoire peut également servir à exécuter du code ! Les compilateurs Just-In-Time peuvent alors y stocker les versions compilées des méthodes. Ainsi, les applications sont efficaces dès la première instruction exécutée. Imaginez une machine virtuelle Java dont toutes les classes ont été préalablement installées en NVRAM ? Le démarrage est alors immédiat. La PermGen (Permanent Generation) devient alors véritablement permanente.
Imaginez un framework d'injection de dépendances qui parcourt l'intégralité des classes Java (ouverture des fichiers, parcours du fichier JAR, décompression du fichier en mémoire, analyse de la structure pour enfin savoir si la classe ou la méthode est annotée comme il faut). Demain, cela sera instantané car maintenu à jour en NVRAM.
Les OS mobiles seront friands de ces approches. En effet, les programmes sont régulièrement interrompus s'ils ne sont pas au premier plan. Dès qu'un programme repasse à l'écran, l'OS doit le redémarrer. Ce dernier va alors relire tous les fichiers de configuration, reprendre son état pour continuer là où il a été interrompu. Avec les NVRAM, les programmes peuvent être simplement endormis et réveillés. Non seulement cela améliorera notablement les performances et le ressenti de l'utilisateur, mais cela économisera énormément la batterie car il n'est alors plus nécessaire de consommer de l'énergie pour maintenir les données en RAM ou relancer les programmes.
REDO Log
Toutes les bases de données SQL ou NoSQL, ont besoin d'un fichier de log qui mémorise toutes les modifications à appliquer aux données. En cas de crash de la base de données, elle est alors en capacité de relire ce fichier pour rejouer les dernières modifications qui n'ont pas encore étés prises en compte par la base. Régulièrement, les modifications de la base de données sont appliquées sur les fichiers et le REDO Log purgé.
C'est seulement lorsque ce fichier a fini d'être écrit sur disque (fsync) que l’acquittement peut être envoyé à l'utilisateur. Cette approche utilise une API spécifique de l'OS (et indirectement du gestionnaire de fichiers) pour garantir la pérennité des données sur la mémoire de masse. Cela fait des millions d'instructions assembleur pour changer le contexte, passer en mode Kernel, analyser et traiter la demande, transmettre les données à sauvegarder au contrôleur disque, attendre que cela soit effectif et revenir vers l'application pour l'informer du résultat de la synchronisation[2].
Avec les NVRAM, les fsync sont remplacés par un flush des caches des processeurs (Instruction CLFLUSH etc.). C'est instantané. En quelques nanosecondes, le REDO Log est enrichi. L’acquittement peut être envoyé sur le réseau.
Avec les NVRAM, les bases de données vont toutes l'utiliser pour y stocker bien plus rapidement les logs des transactions. Ainsi, elles pourront acquitter des modifications aussi rapidement que si elles ne travaillaient qu'en RAM. Les gains de performances à prévoir ne sont pas négligeables.
Une autre évolution est une optimisation des stratégies actuelles de in-memory database des moteurs SQL, pour écrire les mutations des lignes des tables directement en NVRAM. Les performances peuvent être jusqu’à 30 fois plus rapides.
Sérialisation et dé-sérialisation
Tous les programmes sont confrontés à la transformation complexe des structures de données en mémoires pour en faire un fichier à sauvegarder sur disque. Il faut une routine qui va parcourir l'intégralité de la structure pour produire un flux de bytes la représentant. Sauver un fichier Word n'est rien d'autre qu'une sérialisation de la structure de données déjà présente en mémoire.

Demain, il n'y aura plus besoin de ces algorithmes (hors communication réseaux), car les structures en mémoire n'auront tout simplement pas besoin d'être transformées en tableaux de bytes, car les données sont immédiatement exploitable en mémoire persistante, dans leurs structures de prédilection.
Puisqu’il n’est plus nécessaire de sauver des fichiers pour représenter les structures en mémoire, qu'est-ce qu'un répertoire si ce n'est une table de Hash référençant des objets ou d'autres tables de Hash ? Pas besoin d'aller plus loin. Il y a une vingtaine d’années, j’avais évoqué que la gestion de la persistance telle que nous la pratiquions n’était qu’un artefact des limites technologiques de notre époque. Nous venons de lever ces limites. Un “gestionnaire arborescent d’objet” peut être proposé en lieu et place d’un “file system”.
Caches
Les caches sont massivement utilisés dans toutes les technologies. Ils sont alimentés au fur et à mesure de l'utilisation des données. Au démarrage des programmes, ils sont désespérément vides. Demain, les caches seront tous persistants en NVRAM. Le programme n'aura plus besoin de temps de chauffe pour être performant. Cela contribuera aux performances des approches “Server less”.
Actuellement, tous les frameworks avancés sous Java (Cassandra, Spark, etc.) exploitent la mémoire hors-heap (en dehors de la zone mémoire gérée par le ramasse-miette). Cela pour plusieurs raisons :
- Au-delà de 4 à 8 Go, les GC peinent. En travaillant hors heap, on allège la pression en réduisant drastiquement le nombre d'objets à parcourir.
- Cette zone peut servir de cache et être directement alimentée par les drivers de l'OS lors du chargement d'un secteur disque ou d'un paquet réseau. On évite alors les copies coûteuses de tampon vers la mémoire managée par le GC.
- La structure des données est sous le contrôle du développeur. Il n'est pas nécessaire d'avoir des objets répartis dans tout l'espace mémoire (cas des String par exemple). En travaillant hors heap, on peut regrouper tous les attributs les uns à côtés des autres. Ainsi, les caches des processeurs de niveau 1 à 3 sont exploités au maximum de leur potentiel.

Les frameworks utilisant la mémoire hors-heap vont pouvoir être adaptés rapidement pour bénéficier des avantages des NVRAM. Il faut revoir les algorithmes pour s'assurer qu'à tout moment, l'espace mémoire est cohérent.
Des solutions pour améliorer la gestion du Swap de linux existent en bénéficiant des NVRAM. L’idée est d’exploiter le fait que l’accès à la NVRAM ne nécessite pas d’attente de données de la part d’une mémoire de masse de type SSD ou HD, il est possible de supprimer les Context-switch lors de la manipulation de la mémoire virtuelle. Les données sont immédiatement dupliquées de la NVRAM vers la RAM, dans le gestionnaire d’exception chargé du traitement d’une erreur d’accès à une page mémoire.
Une autre astuce consiste à placer la NVRAM devant une mémoire de masse classique. La stratégie d’Anti-caching consiste à ne pas dupliquer les informations entre le disque et la NVRAM. Les données chaudes sont présentes uniquement en NVRAM. Un algorithme de LRU les déplace sur disque. Seul le couple NVRAM+disque est cohérent. Ce n’est plus vraiment un cache, mais un tampon intermédiaire, plus rapide et persistant.
Framework spécifique
Puis viendra le temps du framework novateur dont la conception est dédiée à ces mémoires. L'intégralité du code aura pour vocation d’exploiter au mieux ce modèle de persistance. De nouveaux acteurs vont émerger, des produits reconnus vont devoir évoluer en profondeur pour résister à la concurrence.

Imaginez une base de données NoSQL dont les index sont en NVRAM et, pourquoi pas, intégralement en mémoire non volatile ? Cela est très différent des modèles proposés par Cassandra par exemple. Cette dernière travaille avec un Redo-log et en mémoire, avant de consolider régulièrement sur disque des SSTable immuables. Ce modèle ne résistera probablement pas aux approches intégralement en NVRAM.
De nouveaux algorithmes sont proposés pour les bases SQL, en éliminant les copies de données et en utilisant des pointeurs à la place, afin de réduire les écritures en mémoire.
Imaginez un équivalent des moteurs d'indexation SolR ou Elastic Search, dont la conception serait fondée sur une utilisation des NVRAMs. Le code serait très différent de l'approche actuelle, mais bien plus performant.
Imaginez un gestionnaire de fils de messages conçu pour la mémoire. Il serait différent et probablement plus efficace que les approches zero-copy de Kafka. Les architectures efficaces pour gérer les périphériques en mode bloc, ne le sont pas forcément pour travailler in-memory.
Il existe déjà un module pour MongoDB, un fork de Redis
Évolution des langages
Les langages vont devoir réfléchir à l'intégration profonde des NVRAM. L'approche la plus simple consiste simplement à proposer des librairies pour allouer des objets dans ces espaces, pour proposer des listes ou des MAPs transactionnelles en mémoire. Une librairie C++17 permet de proposer des persistent_ptr<> ().
Mais ce n'est qu'une étape. Il faut aller plus loin en proposant des frameworks orientés complètement sur les transactions en mémoire. On en trouve d’ailleurs déjà pour Scala ou Clojure. De tels frameworks devront évoluer pour garantir la cohérence des données même en cas de crash violent (kill -9 ou interruption électrique).
Une approche proposée pour Java consiste à séparer les objets présent en NVRAM et les objets présent en RAM. Le développeur doit concevoir des objets Java qui ne sont que des wrappers vers les données présentes en NVRAM. Le framework se charge d’instancier les wrappers lorsque cela est nécessaire. Un GC basé sur des compteurs de références s’occupent de gérer la mémoire. De plus, quelques containers persistants sont proposés.
De nouveaux langages proposeront nativement de fonctionner en mode transactionnel. Des syntaxes spécialisées permettront d'isoler les modifications dans des transactions pour garantir la consistance de l'ensemble à tout moment.

Pour gérer les effets de bords en dehors de la mémoire, il faut également prévoir le traitement de rollback.
Des travaux universitaires proposent d’isoler les modifications des threads dans des forks du process, en mode Copy-on-write, d’autres de modifier les compilateurs, etc.
Les verrous proposés par Java peuvent également délimiter les transactions.
Par exemple, imaginons un moteur Javascript dont la frontière transactionnelle correspond à une requête HTTP. Les mutations des objets peuvent être annulées en cas de crash du serveur Node.js par exemple. Avec ce modèle, il est possible d'hiberner une application si elle n'est plus sollicitée. Son réveil sera instantané, le temps de traiter les quelques requêtes en cours.
De même, la compilation Just-In-Time de Javascript s'effectuera en NVRAM ainsi que l'intégralité des allocations.
Finalement, une grande partie des applications pourront être hébergées dans ces mémoires. Avec pour bénéfice immédiat, une belle économie d'énergie et une amélioration notable des performances.
L’émergence de nouveaux OS
Puis viendront de nouveaux OS conçus entièrement pour cette technologie. Le scénario “only NVRAM” nécessite de nouvelles approches.

L'état entier de l'OS sera persistant. Et ce sera une véritable révolution. Les fondamentaux de la conception des OS datent d’un demi-siècle. Ils peuvent être remis profondément en cause. Le postulat “Deux niveaux de stockage (rapide/volatile et lent/non-volatile)” est à abandonner.
L'OS pourra être interrompu et redémarrer instantanément. Plus de phase d'hibernation, de processus à lancer, de structures à construire, etc.
Actuellement, les applications existent sous trois formes : le package avant l’installation, l’état après l’installation dans le système et l’état lors de l'exécution, lorsque le programme est démarré. Demain, installer un programme consistera à le démarrer en mémoire et à le garder indéfiniment. L'exécuter n’a alors plus de sens. On le “sollicite”. Il est toujours disponible et prêt à travailler.
La sécurité basée sur des zones mémoires, la gestion de la mémoire virtuelle ainsi que la gestion en mode “bloc” de la mémoire de masse seront à revoir.
Des TinyOS seront probablement les premiers servis. En répondant aux appels système Linux, il sera possible de relancer une instance nouvelle à chaque nouvelle requête à un serveur WEB ! Comme le propose déjà Amazon avec Lambda, ou Google avec les Cloud Function, les offres Cloud proposeront un coût à la transaction et non aux nombres d'instances de VM, sans impact sur les performances.
Les architectures des ordinateurs seront également remises en cause. Par exemple, les caches des processeurs peuvent posséder les nouvelles versions des données, en cours de modification. Tant que le cache n’est pas vidé, les anciennes versions sont toujours présentes. Cela peut être exploité pour éviter les copies des instances lors de la gestion des transactions en mémoire. Il est ainsi possible de modifier les données sur place, et d’annuler éventuellement les modifications. Intel propose déjà des instructions pour gérer des transactions en mémoire, en exploitant ce modèle. Elles permettent de garantir qu’un ensemble de modification en mémoire sera validé de manière atomique. Un abort invalide toutes les modifications.
Il faudra probablement que les chips soient capables de persister les caches L1 à L3 ainsi que les registres du processeur, lors d’une interruption électrique. Ainsi, à la reprise d’un OS, il sera possible de continuer les traitements en cours via le scheduler, à la position exacte du flot d’exécution des programmes.
Internet of Things
Les objets connectés seront probablement les premiers à bénéficier des ces OS légers et résilients. Ils pourront ainsi être utilisés sans délai. Plus besoin d'attendre le boot de votre Box Internet ou de la caméra IP.
La faible consommation énergétique est également un avantage certain pour intégrer rapidement ces solutions, même au prix d’une légère dégradation des performances.
Par exemple, imaginez une caméra de surveillance qui prend une image toutes les secondes. Entre chaque seconde, le courant peut être coupé, avec un gain non négligeable d'énergie. Une simple pile permet plusieurs années d’utilisation.
Comment commencer
Depuis la version 4.10 du noyau Linux, il y a ce qu’il faut pour travailler. Le site pmem.io est également un mine d’informations et de librairies pour manipuler ces nouveaux jouets.
Si vous avez des idées d'utilisations, partez à la recherche d'investisseurs ! Les Datastax (Cassandra) ou les Confluent.IO (Kafka) de demain sont en train de naître.
Comme toujours, les premiers présents seront les gagnants.
[1] Egalement connues sous le vocable NVDIMM-[NF] pour Non-Volatile Dual In-line Memory Module
[2] Attention aux SSD sans batterie, les caches peuvent être perdus dans le contrôleur.
