OVH Cloud OVH Cloud

Docker et occupation m

19 réponses
Avatar
Yliur
Bonjour

Docker permet de mettre en commun des fichiers entre plusieurs
conteneurs, grâce aux images "ancêtres" des images finales.

Avoir des images ayant une ancêtre commune permet donc de gagner de la
place sur le disque.

Par contre lors de l'exécution, qu'est-ce qui est économisé en mémoire ?
Je suppose que c'est le noyau qui gère le cache système, donc accéder à
un fichier d'une image ancêtre depuis deux conteneurs permet de partager
ce cache ?

D'un point de vue bibliothèques dynamiques, comment ça se passe ? Là en
fait la question dépasse le cadre de docker : comment une bibliothèque
dynamique est-elle "chargée" en mémoire ? Elle apparaît quelque part dans
la mémoire virtuelle d'un processus ? Est-ce que ça implique qu'elle soit
chargée quelque part ou bien c'est une simple correspondance entre ces
adresses virtuelles et le fichier représentant la bibliothèque, en se
contentant d'utiliser le cache système au fur et à mesure que des pages
sont nécessaire ?

Même question pour un processus d'ailleurs : est-ce que le contenu de
l'exécutable est chargé d'une manière spéciale en mémoire, ou bien juste
comme n'importe quel fichier ? En dehors des "méta-données" présentes
dans le fichier exécutable, forcément interprétées par le système au
moment du démarrage de l'exécutable en question.

Et si ce fichier exécutable ou d'une bibliothèque est supprimé lors de
l'exécution, est-ce que ça pose un problème ou bien ce fichier est
considéré comme ouvert et à ce titre son contenu n'est pas supprimé tant
qu'un processus détient une référence à son descripteur ?

Oui, on s'éloigne de docker, mais je me rends compte que ces points sont
assez flous pour moi et que ça m'aurait sans doute permis de répondre à
ma question sur docker...

Merci pour vos lumières :)

Yliur

9 réponses

1 2
Avatar
Yliur
Le Wed, 27 Feb 2019 14:45:55 +0100, Marc SCHAEFER a écrit :
Yliur wrote:
Et donc si le contenu du fichier n'est représenté qu'une seule fois, ça
ne repose pas sur du cache de bas niveau (pages du disque lui-même, en
dessous de la notion de fichier) ? Ce cache se trouve au-dessus de la
notion de fichier ?

Effectivement, j'aurais l'impression que si le numéro d'inode diffère (a
fortiori s'il s'agit de deux points de montage hors cas du mount
--bind),
le partage ne peut avoir lieu. De mémoire, le partage de zones de
`text' (code) est lié au VFS (abstraction filesystem: je pense plus des
dentries que des numéros d'inodes, mais il y a une correspondance).
Pour vraiment répondre à cette question il faudrait consulter
l'implémentation du fs cow que vous utilisez. S'il s'agit d'un simple
overlay sur un FS de plus bas niveau (style unionfs ou le plus ancien
FiST), ça pourrait fonctionner. Si c'est autre chose, style au niveau du
bloc device, non.
Il pourrait toujours y avoir une optimisation de chargement (finalement
le même bloc du disque sous-jacent déjà dans le buffer cache), mais pas
de partage de bibliothèques ou de segment `text'.
Mais je n'en jurerais pas, mon expérience avec le VFS et le cache de
Linux date du kernel 2.4.

D'accord, merci pour les informations.
Avatar
Yliur
Le Wed, 27 Feb 2019 14:46:50 +0000, Nicolas George a écrit :
Yliur , dans le message <q55nbe$kf1$, a écrit :
J'ai des choses à exécuter sur un système d'exploitation donné, je
trouve docker pratique dans ce contexte, plutôt qu'une machine
virtuelle complète par exemple.
Et dans le cadre du déploiement de différentes versions/instances d'une
appli, le cas du partage de fichiers communs (le fonctionnement normal
de docker) est assez courant : les conteneurs déployés ont bien une
base commune.
Je ne comprends pas où tu situes la catastrophe...

Tu présentes les choses comme si la problématique que tu cherches à
résoudre était une donnée immuable, mais ce n'est pas le cas. Tu as le
besoin que tu évoques en premier parce que le logiciel que tu cherches à
utiliser est mal packagé, et les logiciels sont de plus en plus souvent
mal packagés parce que des solutions comme docker existent pour aider à
les faire tourner.

Je ne cherche pas à résoudre un problème, juste à comprendre ce qui se
passe sur le système dans ce cas. Plutôt par curiosité, d'où les
questions parties sur des sujets variés...
D'ailleurs je ne veux pas utiliser un logiciel en particulier, c'est
plutôt qu'on utilise docker pour déployer des logiciels au boulot.
La mise en commun de fichiers (quand on déploie plusieurs fois le
logiciel pour différents clients par exemple, ou mêmes des versions
différentes avec une base commune) c'est juste ce que fait docker par
défaut. Et un jour je me suis demandé si ça valait pour la mémoire
occupée... il semble qu'il y ait de bonnes chances pour que ce soit mis
en commun au niveau des accès au disque, si j'ai bien compris ce que tu
dis : les exécutables et les bibliothèques ne sont pas copiés en mémoire
mais juste associés à une partie de la mémoire virtuelle, et les blocs
correspondant sur le disque sont sans doute chargés de manière unique à
bas niveau par le noyau.
Et en attendant, au revoir les mises à jour de sécurité sur les
bibliothèques.

Étant donné que c'est utilisé en interne chez nous et qu'il faut
redémarrer le système (ou au moins le service) pour que les mises à jour
soient prises en compte, il nous suffit de mettre à jour les images
docker régulièrement et de les redéployer.
Effectivement c'est plus dangereux pour un logiciel tiers fourni sous
cette forme...
Ces pages dans la mémoire virtuelle de processus, elles correspondent à
des blocs du disque directement ? Ou bien un mécanisme de
correspondance plus complexe (par exemple les octets n à m d'un
fichier, peu importe où il est stocké) ?

Elles correspondent à des pages, de même taille, au niveau d'abstraction
« système de fichiers ». C'est un élément fondamental de la gestion
mémoire de Linux.
Quant au lien avec le disque dur, il dépend du filesystem. Pour
beaucoup, la structure en blocs des fichiers est alignée avec la
structure en blocs du périphérique sous-jacent. Dans ce cas, les buffers
de cache du périphérique servent directement de pages de cache. Mais il
y a certains systèmes de fichiers qui font par exemple des économies sur
les blocs en fin de fichier, et dans ce cas il y a un niveau
d'indirection.
Au passage, cette histoire de mmap sur des fichiers, il me semble avoir
vu que c'était parfois utilisé comme optimisation de lecture de
fichiers classiques (dont on veut juste lire le contenu) : c'est parce
qu'au lieu d'allouer un tableau d'octets en mémoire et de copier le
contenu d'un fichier dedans on se contente de faire une association
entre les adresses et le contenu du fichier, donc on évite une
allocation et la recopie de tous les octets en mémoire ? Et peut-être
des appels systèmes pour les lectures successives de blocs dans le
fichier.

Oui, c'est ça. Notons que l'optimisation n'est pas forcément rentable
car jouer sur l'espace d'adressage et provoquer des fautes de page peut
être plus coûteux qu'un appel système bien optimisé.
Le contenu de /proc/$PID/maps laisse entendre que c'est plutôt géré au
niveau du système de fichiers, non ? Il y a des chemins vers les
fichiers dans ce qui s'affiche. À moins que ce ne soit qu'une
indication pour s'y retrouver ?

Ce sont des fichiers qui sont mmapés, ça ne laisse pas grand choix quant
à la manière de l'implémenter.
Du coup une mise à jour de paquets alors que du code s'exécute est
assez dangereuse.

Heureusement que les gestionnaires de paquets suppriment les fichiers
avant de les écraser.

D'accord.
Merci pour toutes tes explications.
Avatar
Nicolas George
Yliur , dans le message <q5bch9$kq7$, a écrit :
Je ne cherche pas à résoudre un problème, juste à comprendre ce qui se
passe sur le système dans ce cas. Plutôt par curiosité, d'où les
questions parties sur des sujets variés...

Je parlais de la catastrophe docker dans l'absolu, pas spécifiquement
dans ton cas.
les exécutables et les bibliothèques ne sont pas copiés en mémoire
mais juste associés à une partie de la mémoire virtuelle, et les blocs
correspondant sur le disque sont sans doute chargés de manière unique à
bas niveau par le noyau.

Euh, non. Les blocs sont chargés à la demande puisqu'ils sont toujours
disponibles dans le fichier, mais le processeur ne peut exécuter de code
qu'en mémoire, et recharger en permanence serait catastrophique pour les
performances.
Donc en conditions normales, une bibliothèque finit en général
rapidement chargée intégralement en mémoire.
C'est plus efficace qu'une bête allocation parce que c'est la même
mémoire physique pour tous les exemplaires, et aussi parce qu'en cas de
manque de mémoire il n'y a pas besoin de les copier dans le swap, il
suffit de les libérer immédiatement pour les relire plus tard. Mais si
on manque de mémoire au point que ça fasse une différence on est déjà
cuit.
Il peut y avoir un léger avantage quand c'est une énorme bibliothèque
dont toutes les applications n'utilisent qu'une petite partie.
Avatar
Lucas Levrel
Le 1 mars 2019, à 09:52, Pascal J. Bourguignon a écrit :
Lucas Levrel writes:
Le 27 février 2019, à 10:04, Yliur a écrit :
Au passage, cette histoire de mmap sur des fichiers, il me semble avoir
vu que c'était parfois utilisé comme optimisation de lecture de fichiers
classiques (dont on veut juste lire le contenu) : c'est parce qu'au lieu
d'allouer un tableau d'octets en mémoire et de copier le contenu d'un
fichier dedans on se contente de faire une association entre les adresses
et le contenu du fichier, donc on évite une allocation et la recopie de
tous les octets en mémoire ? Et peut-être des appels systèmes pour les
lectures successives de blocs dans le fichier.

La seule fois où j'ai utilisé un mmap dans un code, ça a chargé
l'intégralité du fichier en mémoire dès l'appel (peut-être même que
l'appel a été bloquant, je ne sais plus), alors que mon but était
évidemment de l'éviter. À mon avis (je ne suis pas informaticien) il y
a tellement de niveaux d'optimisation entre le code source et
l'exécution qu'il est difficile de prévoir, sur la base du source,
comment un code va s'exécuter.
Je crossposte sur fr.comp.lang.c

mmap ne charge pas l'intégralité du fichier. En fait, il ne charge
absolument rien. Il ne fait que réserver les adresses en mémoire
virtuelle.
Une page du fichier n'est lue (chargée en mémoire) que lorsqu'on y
accède.

Effectivement, par défaut oui ; mais il y a le drapeau MAP_POPULATE. J'ai
retrouvé le (vieux) code et j'avais aussi testé
madvise(...MADV_SEQUENTIAL), d'où sans doute mon souvenir erroné. Désolé
pour le bruit.
--
LL
Avatar
Lucas Levrel
Le 28 février 2019, à 11:05, Nicolas George a écrit :
Je crossposte sur fr.comp.lang.c

mmap() n'a rien à voir avec le C, fu2 repositionné vers le groupe de
départ, moins inadapté.

« rien à voir » est peut-être un peu extrême ?
Le crosspost n'indiquait pas que mmap() est une primitive du C ; mais je
savais qu'il y avait là-bas du monde susceptible d'intervenir.
--
LL
Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Avatar
Lucas Levrel
Le 1 mars 2019, à 08:33, Marc Espie a écrit :
In article ,
Lucas Levrel wrote:
Le 27 février 2019, à 10:04, Yliur a écrit :
Au passage, cette histoire de mmap sur des fichiers, il me semble avoir
vu que c'était parfois utilisé comme optimisation de lecture de fichiers
classiques (dont on veut juste lire le contenu) : c'est parce qu'au lieu
d'allouer un tableau d'octets en mémoire et de copier le contenu d'un
fichier dedans on se contente de faire une association entre les adresses
et le contenu du fichier, donc on évite une allocation et la recopie de
tous les octets en mémoire ? Et peut-être des appels systèmes pour les
lectures successives de blocs dans le fichier.

La seule fois où j'ai utilisé un mmap dans un code, ça a chargé
l'intégralité du fichier en mémoire dès l'appel (peut-être même que
l'appel a été bloquant, je ne sais plus), alors que mon but était
évidemment de l'éviter. À mon avis (je ne suis pas informaticien) il y a
tellement de niveaux d'optimisation entre le code source et l'exécution
qu'il est difficile de prévoir, sur la base du source, comment un code va
s'exécuter.

Ton avis est faux concernant mmap. Je ne sais pas ce que tu as branlé, mais
à partir du moment où tu utilises mmap, ben c'est l'OS qui s'y colle, donc
c'est raisonnablement prévisible, bien au contraire.
Evidemment que la résolution du nom de fichier est bloquante, et la
réservation de pages dans ton espace mémoire aussi. Pour la lecture à
proprement parler, non pas trop. Mais il faut évidemment que le fichier
fasse une certaine taille pour que ça présente un intérêt.
Il n'y a pas tant de niveaux d'optimisation que ça, et c'est relativement
facile de jeter un oeil au code assembleur en cas de gros doute.

SidhaSBwcm9iYWJsZW1lbnQgZMOpY29ubsOpLiBDZWNpIMOpdGFudCwgaidh
dXJhaXMgdGVuZGFuY2Ugw6AgZGlyZSBxdWUgcXVhbmQgbCdPUwpzJ3kgY29s
bGUgYydlc3QgZW5jb3JlIG1vaW5zIHByw6l2aXNpYmxlLCB2dSBxdSdpbCBn
w6hyZSB0b3VzIGxlcyBhdXRyZXMgcHJvY2Vzc3VzCnNpbXVsdGFuw6ltZW50
Li4uIFBvdXIgY2UgcXVpIGVzdCBkdSBjb2RlIGFzc2VtYmxldXIsIG9uIG4n
YSBwYXMgbGEgbcOqbWUgbm90aW9uCmR1IMKrIHJlbGF0aXZlbWVudCBmYWNp
bGUgwrssIG1haXMgYydlc3Qgbm9ybWFsLCBvbiBuZSBmYWl0IHBhcyBsZSBt
--
LL
Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Avatar
Lucas Levrel
Le 1 mars 2019, à 17:48, Lucas Levrel a écrit :
Le 1 mars 2019, à 08:33, Marc Espie a écrit :
Ton avis est faux concernant mmap. Je ne sais pas ce que tu as branlé,
mais
à partir du moment où tu utilises mmap, ben c'est l'OS qui s'y colle,
donc
c'est raisonnablement prévisible, bien au contraire.
Evidemment que la résolution du nom de fichier est bloquante, et la
réservation de pages dans ton espace mémoire aussi. Pour la lecture à
proprement parler, non pas trop. Mais il faut évidemment que le fichier
fasse une certaine taille pour que ça présente un intérêt.
Il n'y a pas tant de niveaux d'optimisation que ça, et c'est relativement
facile de jeter un oeil au code assembleur en cas de gros doute.

SidhaSBwcm9iYWJsZW1lbnQgZMOpY29ubsOpLiBDZWNpIMOpdGFudCwgaidh
dXJhaXMgdGVuZGFuY2Ugw6AgZGlyZSBxdWUgcXVhbmQgbCdPUwpzJ3kgY29s
bGUgYydlc3QgZW5jb3JlIG1vaW5zIHByw6l2aXNpYmxlLCB2dSBxdSdpbCBn
w6hyZSB0b3VzIGxlcyBhdXRyZXMgcHJvY2Vzc3VzCnNpbXVsdGFuw6ltZW50
Li4uIFBvdXIgY2UgcXVpIGVzdCBkdSBjb2RlIGFzc2VtYmxldXIsIG9uIG4n
YSBwYXMgbGEgbcOqbWUgbm90aW9uCmR1IMKrIHJlbGF0aXZlbWVudCBmYWNp
bGUgwrssIG1haXMgYydlc3Qgbm9ybWFsLCBvbiBuZSBmYWl0IHBhcyBsZSBt

w6ptZSBtw6l0aWVyLi4uCg
(désolé, le coup est parti trop vite :-) )
--
LL
Avatar
Yliur
Le Fri, 01 Mar 2019 14:15:20 +0000, Nicolas George a écrit :
Yliur , dans le message <q5bch9$kq7$, a écrit :
Je ne cherche pas à résoudre un problème, juste à comprendre ce qui se
passe sur le système dans ce cas. Plutôt par curiosité, d'où les
questions parties sur des sujets variés...

Je parlais de la catastrophe docker dans l'absolu, pas spécifiquement
dans ton cas.
les exécutables et les bibliothèques ne sont pas copiés en mémoire
mais juste associés à une partie de la mémoire virtuelle, et les blocs
correspondant sur le disque sont sans doute chargés de manière unique à
bas niveau par le noyau.

Euh, non. Les blocs sont chargés à la demande puisqu'ils sont toujours
disponibles dans le fichier, mais le processeur ne peut exécuter de code
qu'en mémoire, et recharger en permanence serait catastrophique pour les
performances.
Donc en conditions normales, une bibliothèque finit en général
rapidement chargée intégralement en mémoire.
C'est plus efficace qu'une bête allocation parce que c'est la même
mémoire physique pour tous les exemplaires, et aussi parce qu'en cas de
manque de mémoire il n'y a pas besoin de les copier dans le swap, il
suffit de les libérer immédiatement pour les relire plus tard. Mais si
on manque de mémoire au point que ça fasse une différence on est déjà
cuit.
Il peut y avoir un léger avantage quand c'est une énorme bibliothèque
dont toutes les applications n'utilisent qu'une petite partie.

C'est bien ce que j'avais compris, même si j'ai peut-être mal résumé la
situation.
Merci.
Avatar
Nicolas George
Lucas Levrel , dans le message
, a écrit :
« rien à voir » est peut-être un peu extrême ?

Non, pas du tout.
Le crosspost n'indiquait pas que mmap() est une primitive du C ; mais je
savais qu'il y avait là-bas du monde susceptible d'intervenir.

Comme certains achètent des listes d'adresses électroniques de gens
« susceptibles » d'être intéressés par des pilules bleues. Oui, il y a
probablement des gens intéressés à la fois par le C et par Unix, et ces
gens-là seront abonnés aux groupes consacrés au C et à ceux consacrés à
Unix. En revanche, il y a aussi des gens intéressés par le C et pas par
Unix, qui s'abonnent uniquement aux groupes consacrés aux C. Ton xpost a
été discourtois envers ces derniers.
1 2