Forcer le répertoire à toujours être en cache

35

J'ai testé différentes méthodes pour améliorer le temps nécessaire à la compilation de l'ensemble de mon projet c ++. Actuellement, cela prend ~ 5 minutes. J'ai expérimenté avec distcc, ccache et autres. Récemment, j'ai découvert que si je copiais l'intégralité de mon projet sur un lecteur de mémoire vive, puis que je compilais à partir de là, le temps de compilation était réduit à 30% de son temps d'origine, à savoir 1,5 minute.

Évidemment, travailler à partir du lecteur de RAM n'est pas pratique. Alors, est-ce que quelqu'un connaît un moyen de forcer le système d'exploitation à toujours garder un répertoire en cache ? Je veux toujours que le répertoire soit synchronisé sur le disque comme d'habitude, mais je veux toujours aussi une copie des données en mémoire. Est-ce possible?

EDIT: Comme solution possible, nous avons simplement pensé à lancer un démon qui s'exécute rsynctoutes les 10 secondes environ pour synchroniser le lecteur de disque avec un lecteur RAM. Ensuite, nous exécutons la compilation à partir du lecteur RAM. Le rsyncest flamboyant, mais cela fonctionnerait-il vraiment? L'OS pourrait sûrement faire mieux ....

JaredC
la source
Le cache n'est pas la seule différence entre tmpfs et ext3 / 4; ils ont par exemple une journalisation qui sera écrite indépendamment de la mise en cache.
André Paramés le
1
Pourriez-vous timevotre compilation et partager le résultat avec nous? Cela dissiperait une certaine controverse. make clean && /usr/bin/time -v make(n'utilisez pas la timecommande intégrée bash )
shellholic
1
@she Pourquoi ne pas la commande intégrée de bash?
Tshepang
3
@Tshepang la timebash intégrée ( help time) a beaucoup moins de détails (pas d'option verbeuse) que l'heure GNU ( man time) concernant les entrées / sorties, le changement de contexte, ...
shellholic

Réponses:

18

La façon évidente de garder un tas de fichiers dans le cache est d'y accéder souvent. Linux est plutôt doué pour arbitrer entre la permutation et la mise en cache. Je suppose donc que la différence de vitesse que vous observez n’est pas due au fait que le système d’exploitation ne garde pas les choses en cache, mais à une autre différence entre votre utilisation de tmpfs et vos autres tentatives.

Essayez d'observer ce que fait IO dans chaque cas. L'outil de base pour cela est iotop. D'autres outils peuvent être utiles. voir la répartition de la charge d'E / S du disque Linux, par chemin et / ou processus du système de fichiers? , Quel programme sous Linux peut mesurer les E / S au fil du temps? , et d’autres threads sur Server Fault.

Voici quelques hypothèses sur ce qui pourrait se passer. Si vous prenez des mesures, montrez-les afin que nous puissions confirmer ou infirmer ces hypothèses.

  • Si les heures d’accès aux fichiers sont activées, le système d’exploitation risque de perdre un peu de temps à les écrire. Les temps d'accès sont inutiles pour un arbre de compilation, assurez-vous qu'ils sont désactivés avec l' noatimeoption de montage. Votre solution tmpfs + rsync ne lit jamais à partir du disque dur, elle n’a donc jamais besoin de passer plus de temps à écrire.
  • Si les écritures se synchronisent , soit parce que le compilateur appelle, sync()soit parce que le noyau vide fréquemment ses tampons de sortie, les écritures prendront plus de temps sur un disque dur que sur tmpfs.
Gilles, arrête de faire le mal
la source
J'ai ce sentiment aussi. La compilation nécessite beaucoup de ressources en processeur et non en IO.
Phunehehe
Hmmm, j'aimerais voir un commentaire de @JaredC confirmer ou infirmer l'hypothèse de Gilles. 1,5 contre 5 minutes, c'est une grosse différence ...
Daniel Alder
8

Linux utilise par défaut la RAM comme cache disque. En guise de démonstration, essayez de l'exécuter time find /some/dir/containing/a/lot/of/files > /dev/nulldeux fois, la deuxième fois est beaucoup plus rapide car tous les inodes de disque sont mis en cache. Le point ici est de savoir comment utiliser cette fonctionnalité du noyau et arrêter votre tentative de la remplacer.

Le but est de changer le swappiness. Prenons trois types principaux d’utilisation de la mémoire: les programmes actifs, les programmes inactifs et le cache disque. Évidemment, la mémoire utilisée par les programmes actifs ne doit pas être permutée et le choix entre deux autres est assez arbitraire. Voulez-vous un changement rapide de programme ou un accès rapide à un fichier? Un swapiness faible préfère conserver les programmes en mémoire (même s'il n'est pas utilisé pendant une longue période) et un swappiness élevé préfère conserver davantage de cache disque (en échangeant les programmes inutilisés). (L'échelle de swappiness va de 0 à 100 et la valeur par défaut est 60)

Ma solution à votre problème est de changer le swappiness à très haut (90-95 pour ne pas dire 100) et de charger le cache:

echo 95 | sudo tee /proc/sys/vm/swappiness > /dev/null # once after reboot
find /your/source/directory -type f -exec cat {} \; > /dev/null

Comme vous le devinez, vous devez disposer de suffisamment de mémoire libre pour stocker en cache tous vos fichiers source et objets, ainsi que le compilateur, les fichiers d’entêtes inclus, les bibliothèques liées, votre IDE et d’autres programmes utilisés.

shellholic
la source
C’est utile en général, mais ce que je veux vraiment, c’est que mon code source soit peu swappiness, mais que tout le reste soit swappiness normal. Essentiellement, il y a beaucoup de choses qui se passent à l'arrière-plan, mais je veux les limiter à 6 Go sur 8 Go, tout en conservant toujours les 2 Go restants pour le code source. Je ne veux pas prendre le risque qu'il soit échangé ... jamais ... parce que c'est ennuyeux.
JaredC
Swappiness est à l'échelle du système. En fait, si vous faites autre chose et que vos fichiers sont déchargés de la mémoire, il vous suffit de le recharger avec la deuxième ligne. Si la mémoire doit être libérée pour autre chose, vous ne "voulez vraiment pas prendre le risque", cela doit être fait à partir d'un échange. BTW, tmpfsdans le même cas serait également échangé.
shellholic
2
Personnellement, je suis tombé un swapiness élevé est abominablement horrible sur les postes de travail. Bien que certaines fonctions puissent être accélérées par le cache plus important (c'est-à-dire plus de fichiers en cache), cela a un prix: vous payez cela en termes de réactivité lors du changement de programme, ce que les utilisateurs remarquent en premier lorsqu'ils travaillent sur un système. Lorsque je passe d'un navigateur à un autre navigateur, je ne peux tout simplement pas supporter d'attendre 1-2 secondes pour que chaque programme réapparaisse. Sur tous mes ordinateurs Linux, je règle généralement swappiness sur une valeur faible de 10.
fgysin réintègre Monica
6

Forcer le cache n'est pas la bonne façon de faire. Mieux vaut garder les sources sur le disque dur et les compiler sur les fichiers tmpfs. De nombreux systèmes de compilation, tels que qmake et CMake, prennent en charge les versions hors source.

Gelraen
la source
6

Le inosyncdémon sonne comme si il faisait exactement ce que vous voulez si vous voulez rsync sur un disque mémoire. Au lieu de rynchroniser toutes les 10 secondes environ, il utilise la fonction inotify de Linux pour rsync lorsqu'un fichier est modifié. Je l'ai trouvé dans le référentiel Debian en tant que inosyncpaquet, ou sa source est disponible à l' adresse http://bb.xnull.de/projects/inosync/ .

Jander
la source
Cela semble très utile. Je vais y regarder et faire rapport. Merci!
JaredC
5

Cette chose semble fonctionner pour moi si je veux garder certains fichiers ou tous les fichiers d'un certain répertoire dans le cache.

vmtouch semble faire juste la chose. Exemple 5 il pourrait y avoir ce dont vous avez besoin.

vmtouch -dl /whatever/directory/

Je devais l'exécuter en tant que root avec sudo

Highstaker
la source
1
Il ne voit pas les fichiers nouveaux / supprimés.
Vi.
3

Avec suffisamment de mémoire, votre construction à partir du disque mémoire ne fait pas d’E / S. Cela peut accélérer tout ce qui lit ou écrit des fichiers. I / O est l'une des opérations les plus lentes. Même si tout est mis en cache avant la construction, vous avez toujours les entrées / sorties pour l'écriture, bien qu'elles aient un impact minimal.

Vous pouvez obtenir une certaine accélération en préchargeant tous les fichiers dans le cache, mais le temps nécessaire à cela doit être inclus dans le temps total de génération. Cela peut ne pas vous donner beaucoup d'avantages.

Construire l'objet et les fichiers intermédiaires dans la RAM plutôt que sur le disque. Faire des builds incrémentiels peut vous apporter des gains significatifs sur les builds fréquents. Sur la plupart des projets, j'effectue quotidiennement une construction propre et incrémentielle. Les versions d'intégration sont toujours propres, mais j'essaie de les limiter à moins d'une par jour.

Vous pouvez obtenir des performances en utilisant une partition ext2 avec atime désactivé. Votre source doit être sous contrôle de version sur un système de fichiers journalisé tel qu'ext3 / 4.

BillThor
la source
2

Comme indiqué précédemment, la méthode évidente consiste à lire toute la structure de répertoires et le contenu du fichier de ce que vous souhaitez mettre en cache.

Vous pouvez automatiser cela en écrivant un script pour surveiller la sortie de vmstat 1(utilisez n'importe quel outil équivalent pour votre système d'exploitation) et en gardant la somme du nombre de blocs écrits et lus. Une fois que la somme dépasse un seuil de votre choix, lisez tous les fichiers que vous souhaitez mettre en cache, réinitialisez la somme, puis continuez à surveiller la sortie de vmstat. Pour une lecture rapide des fichiers: si votre arborescence contient de nombreux fichiers, évitez find ... -exec catplutôt d'essayer find ... -print0 | xargs -0 catun programme personnalisé qui n'exécutera pas cat pour chaque fichier.

La surveillance des E / S de disque est préférable à l’utilisation d’un intervalle fixe, car elle signale la relecture plus ou moins fréquente de vos données en fonction de la charge d’E / S du disque.

J'ai utilisé cette méthode automatisée avec succès sur des systèmes nécessitant des lectures de fichiers d'index toujours rapides, évitant les E / S de disque dur. J'ai également utilisé strace pour créer une liste de tous les fichiers auxquels on accède lorsque je me connecte afin de pouvoir tout conserver en mémoire cache pour des connexions rapides.

Ce n'est peut-être pas la meilleure solution possible mais cela me convenait bien.

filebarn
la source