2009-07-10 7 views
4

J'ai une application C++ fonctionnant sous Windows qui se réveille toutes les 15 minutes pour ouvrir & lire les fichiers présents dans un répertoire. Le répertoire change à chaque exécution.Optimiser le fichier ouvrir et lire

  • ouverte est réalisée par ifstream.open (nom_fichier, std :: ios :: binaires)
  • lecture est effectuée par streambuf ios :: rdbuf() *
  • Nombre total de fichiers toutes les 15 minutes est d'environ 50 000
  • Les fichiers sont ouverts & lu par lots de 20
  • La taille de chaque fichier est d'environ 50 kilo-octets

Pour chaque série; cette opération (ouverte & read) prend environ 18-23 minutes sur une machine dual-core avec une vitesse de broche de 6000 tr/min. J'ai capturé le défaut de la page de mémoire/sec et ils sont dans la gamme de 8000 - 10000.

Y at-il un moyen de réduire les défauts de page et optimiser le fichier ouvert & opération de lecture?

Gowtham

+0

Vous ne dites pas comment vous lisez depuis le rdbuf. Sauf si vous lisez le fichier entier en un seul appel, essayez de définir le tampon dans rdbuf à la taille du fichier. C'est un changement de code très simple, ça vaut l'expérience, et ça peut aider beaucoup. Si le code lit actuellement 20 fichiers à la fois en petits morceaux de quelques kb, alors le disque pourrait faire jusqu'à une recherche par morceau. Donc tampon plus gros => plus gros morceaux => moins de recherche => plus vite. Espérons. Bien sûr, cela peut ne faire aucune différence puisque Windows risque de mettre en cache le fichier entier de manière spéculative. –

Répondre

3

Ne pas utiliser STL si vous pouvez l'éviter. Il gère des problèmes d'internationalisation et de traduction/transformation très difficiles qui le ralentissent. Le plus souvent, le moyen le plus rapide de lire un fichier est de le mapper en mémoire (également sous Windows, CreateFileMapping as starting point) Si possible, utilisez un seul fichier d'une taille totale de 50'000 * 50K et indexez directement ce fichier lorsque écriture/lecture Vous devriez aussi envisager d'utiliser une base de données (même SQLite) si les données sont structurées du tout.Cette quantité de données est si petite qu'elle devrait rester en mémoire à tout moment.Vous pouvez également essayer d'utiliser ramdisk pour éviter d'aller à disque du tout (cela va taxer votre récupération d'erreur en cas de panne matérielle/électrique)

+1

"Il gère des problèmes d'internationalisation et de traduction/transformation très difficiles qui le ralentissent." Cela dépend entièrement de la mise en œuvre. Si vous effectuez les opérations de lecture au niveau streambuf alors il ne devrait pas y avoir de problèmes de formatage i18n et il est tout à fait raisonnable (même préférable) pour l'implémentation de ne pas effectuer et encoder les transformations, en passant par les octets stockés sur disque. –

+0

Sur une machine dual core avec un disque 6000RPM, je serais légèrement surpris s'il dispose de 2,5 Go de RAM pour un disque RAM. Mais cela accélérerait certainement les choses s'il le faisait. –

0

Selon la documentation de MS PSDK, la mise en cache des fichiers peut être utilisée Et, à mon humble avis, au lieu de STL, windows native CreatFile, ReadFile et CloseHandle avec des drapeaux appropriés peuvent obtenir une meilleure performance puisque vous fenêtres mentionnées.

Mais, d'un autre côté, d'après votre article, il semble que vous ayez seulement lu. Ainsi, la mise en cache peut ne pas augmenter les performances de manière significative. Mais, étant donné que le processeur est rapide et que les entrées/sorties disque sont généralement lentes, vous pouvez toujours utiliser ce type de tampon intermédiaire avec multithreading, ce qui signifie exécuter des threads de lecture parallèles.

0
  1. Peut-être que vous pouvez utiliser quelque chose comme mémoïsation, à savoir si le fichier n'a pas changé (vous pouvez l'enregistrer est la dernière fois mise à jour), vous pouvez l'utiliser depuis la dernière fois, i.e. garder quelque chose en mémoire à la place.

  2. Je pense que vous n'avez pas besoin de mise en cache FS. C'est à dire. il vaudra mieux ouvrir les fichiers en mode O_DIRECT (c'est Linux, mais je suis sûr que Windows a quelque chose de similaire) et lire chaque fichier dans une E/S, c'est-à-dire créer un tampon en mémoire de la taille du fichier. Cela devrait réduire considérablement l'utilisation du processeur et de la mémoire.

  3. Multi-threading, suggéré ci-dessus, aidera également, mais pas beaucoup. Je soupçonne que le goulot de la bouteille est le disque, qui peut effectuer une quantité limitée d'opérations d'E/S par seconde (100 peut être une estimation). C'est pourquoi vous devez réduire la quantité d'opérations d'E/S, comme utiliser (1), (2) décrit ci-dessus ou autre chose.

1

Premièrement; Merci pour toutes les réponses. C'était très utile et nous a fourni de nombreuses avenues à explorer.

Nous avons supprimé STL et utilisé C (fopen & fread). Ceci nous a fourni une légère amélioration avec l'opération de lecture Open & pour les données mentionnées ci-dessus, prenant de 16 à 17 minutes.

Nous avons vraiment résolu le problème en compressant ces fichiers. Cela a réduit la taille de chaque fichier de 50K à 8K. Le temps pris par l'opération de lecture Open & a été réduit à 4 - 5 minutes.

Merci.

Questions connexes