E / S de fichier avec stream – meilleure taille de la mémoire tampon

J’écris une petite bibliothèque I / O pour aider avec un projet plus grand (passe-temps). Une partie de cette bibliothèque exécute diverses fonctions sur un fichier, qui est lu / écrit via l’object FileStream . Sur chaque StreamReader.Read(...) passe,

Je déclenche un événement qui sera utilisé dans l’application principale pour afficher les informations de progression. Le traitement qui se déroule dans la boucle est vaired, mais ne prend pas trop de temps (il peut s’agir d’une simple copie de fichier, par exemple, ou peut impliquer un cryptage …).

Ma principale question est la suivante: quelle est la meilleure taille de mémoire tampon à utiliser? En ce qui concerne la disposition des disques physiques, je pourrais choisir 2 ko, ce qui couvrirait une taille de secteur de CD et serait un bon multiple d’un secteur de disque dur de 512 octets. Plus haut dans l’arbre d’abstraction, vous pouvez choisir un tampon plus grand capable de lire un cluster FAT entier à la fois. Je me rends compte avec les PC d’aujourd’hui, je pourrais opter pour une option plus gourmande en mémoire (quelques MiB, par exemple), mais j’augmente le temps entre les mises à jour de l’interface utilisateur et l’utilisateur perçoit une application moins réactive.

En passant, j’espère finalement fournir une interface similaire aux fichiers hébergés sur des serveurs FTP / HTTP (via un réseau local / fast DSL). Quelle serait la meilleure taille de mémoire tampon pour ceux-ci (encore une fois, un compromis «meilleur cas» entre la réactivité perçue et la performance)?

Les fichiers sont déjà mis en mémoire tampon par le cache du système de fichiers. Vous avez juste besoin de choisir une taille de tampon qui ne force pas FileStream à faire l’appel API Windows ReadFile () natif pour remplir le tampon trop souvent. Ne dépassez pas un kilo-octet, plus de 16 Ko est un gaspillage de mémoire et peu favorable au cache L1 du processeur (généralement 16 ou 32 Ko de données).

4 Ko est un choix traditionnel, même si cela ne concerne que par accident une page de mémoire virtuelle. C’est difficile à profiler; vous finirez par mesurer le temps nécessaire pour lire un fichier en cache. Qui fonctionne à des vitesses de RAM, 5 gigaoctets / s et plus si les données sont disponibles dans le cache. Il sera dans le cache la deuxième fois que vous exécuterez votre test, et cela n’arrivera pas trop souvent dans un environnement de production. Les E / S sur fichiers sont complètement dominées par le lecteur de disque ou la carte réseau et sont extrêmement lentes, la copie des données étant des arachides. 4 Ko fonctionneront bien.

Lorsque je traite des fichiers directement via un object de stream, j’utilise généralement 4096 octets. Il semble être raisonnablement efficace sur plusieurs zones d’E / S (système de fichiers local, LAN / SMB , stream réseau, etc.), mais je ne l’ai ni profilé ni rien. Il y a longtemps, j’ai vu plusieurs exemples utiliser cette taille, et celle-ci est restée dans ma mémoire. Cela ne signifie pas que c’est le meilleur.

“Ça dépend”.

Vous devrez tester votre application avec différentes tailles de tampons pour déterminer ce qui convient le mieux. Vous ne pouvez pas deviner à l’avance.

Je suppose que la valeur par défaut est la meilleure – par conséquent, j’utilise 4096B basé sur internal const int variable internal const int DefaultBufferSize dans la classe FileStream .