La taille optimale du tampon est liée à un certain nombre de choses: la taille du bloc du système de fichiers, la taille du cache du processeur et la latence du cache.
La plupart des systèmes de fichiers sont configurés pour utiliser des tailles de bloc de 4096 ou 8192. En théorie, si vous configurez la taille de votre tampon de manière à lire quelques octets de plus que le bloc de disque, les opérations avec le système de fichiers peuvent être extrêmement inefficaces (c'est-à-dire si vous configuré votre tampon pour lire 4100 octets à la fois, chaque lecture nécessiterait 2 lectures de bloc par le système de fichiers). Si les blocs sont déjà dans le cache, vous finissez par payer le prix de la RAM -> latence du cache L3 / L2. Si vous n'êtes pas chanceux et que les blocs ne sont pas encore en cache, vous payez également le prix de la latence disque-> RAM.
C'est pourquoi vous voyez la plupart des tampons dimensionnés comme une puissance de 2, et généralement supérieure (ou égale) à la taille du bloc de disque. Cela signifie qu'une de vos lectures de flux peut entraîner plusieurs lectures de bloc de disque - mais ces lectures utiliseront toujours un bloc complet - pas de lectures gaspillées.
Maintenant, cela est un peu décalé dans un scénario de streaming typique car le bloc qui est lu à partir du disque sera toujours en mémoire lorsque vous frappez la prochaine lecture (nous faisons des lectures séquentielles ici, après tout) - donc vous vous retrouvez payer la RAM -> prix de latence du cache L3 / L2 à la prochaine lecture, mais pas la latence disque-> RAM. En termes d'ordre de grandeur, la latence disque-> RAM est si lente qu'elle comble à peu près toute autre latence que vous pourriez avoir à gérer.
Donc, je soupçonne que si vous exécutez un test avec différentes tailles de cache (je ne l'ai pas fait moi-même), vous constaterez probablement un impact important de la taille du cache jusqu'à la taille du bloc du système de fichiers. Au-dessus de cela, je soupçonne que les choses se stabiliseraient assez rapidement.
Il y a une tonne de conditions et d'exceptions ici - les complexités du système sont en fait assez stupéfiantes (le simple fait de maîtriser les transferts de cache L3 -> L2 est incroyablement complexe, et cela change avec chaque type de processeur).
Cela conduit à la réponse du `` monde réel '': si votre application est à 99%, définissez la taille du cache sur 8192 et continuez (mieux encore, choisissez l'encapsulation plutôt que les performances et utilisez BufferedInputStream pour masquer les détails). Si vous êtes dans le 1% des applications qui dépendent fortement du débit du disque, concevez votre implémentation afin de pouvoir échanger différentes stratégies d'interaction de disque, et fournissez les boutons et les molettes pour permettre à vos utilisateurs de tester et d'optimiser (ou d'en proposer système d'auto-optimisation).
Oui, cela dépend probablement de diverses choses - mais je doute que cela fasse une grande différence. J'ai tendance à opter pour 16K ou 32K comme un bon équilibre entre l'utilisation de la mémoire et les performances.
Notez que vous devriez avoir un bloc try / finally dans le code pour vous assurer que le flux est fermé même si une exception est levée.
la source
Dans la plupart des cas, cela n'a pas vraiment d'importance. Choisissez simplement une bonne taille telle que 4K ou 16K et respectez-la. Si vous êtes certain qu'il s'agit du goulot d'étranglement dans votre application, vous devez commencer le profilage pour trouver la taille de tampon optimale. Si vous choisissez une taille trop petite, vous perdrez du temps à effectuer des opérations d'E / S supplémentaires et des appels de fonctions supplémentaires. Si vous choisissez une taille trop grande, vous commencerez à voir beaucoup d'erreurs de cache qui vous ralentiront vraiment. N'utilisez pas de tampon plus grand que la taille de votre cache L2.
la source
Dans le cas idéal, nous devrions avoir suffisamment de mémoire pour lire le fichier en une seule opération de lecture. Ce serait le plus performant car nous laissons le système gérer le système de fichiers, les unités d'allocation et le disque dur à volonté. En pratique, vous avez la chance de connaître la taille des fichiers à l'avance, il suffit d'utiliser la taille moyenne des fichiers arrondie à 4K (unité d'allocation par défaut sur NTFS). Et le meilleur de tous: créez un benchmark pour tester plusieurs options.
la source
Vous pouvez utiliser les BufferedStreams / lecteurs, puis utiliser leurs tailles de tampon.
Je crois que les BufferedXStreams utilisent 8192 comme taille de tampon, mais comme Ovidiu l'a dit, vous devriez probablement exécuter un test sur tout un tas d'options. Cela dépendra vraiment du système de fichiers et des configurations de disque pour savoir quelles sont les meilleures tailles.
la source
La lecture de fichiers à l'aide de FileChannel et de MappedByteBuffer de Java NIO aboutira très probablement à une solution qui sera beaucoup plus rapide que toute solution impliquant FileInputStream. Fondamentalement, mappez en mémoire les gros fichiers et utilisez des tampons directs pour les petits.
la source
Dans la source de BufferedInputStream, vous trouverez: private static int DEFAULT_BUFFER_SIZE = 8192;
Vous pouvez donc utiliser cette valeur par défaut.
Mais si vous pouvez trouver plus d'informations, vous obtiendrez des réponses plus valables.
Par exemple, votre adsl peut préférer un tampon de 1454 octets, car la charge utile de TCP / IP. Pour les disques, vous pouvez utiliser une valeur correspondant à la taille de bloc de votre disque.
la source
Comme déjà mentionné dans d'autres réponses, utilisez BufferedInputStreams.
Après cela, je suppose que la taille du tampon n'a pas vraiment d'importance. Soit le programme est lié aux E / S, et l'augmentation de la taille de la mémoire tampon par rapport à la valeur par défaut BIS n'aura aucun impact important sur les performances.
Ou le programme est lié au processeur dans MessageDigest.update (), et la majorité du temps n'est pas passée dans le code de l'application, donc le peaufiner n'aidera pas.
(Hmm ... avec plusieurs cœurs, les threads pourraient aider.)
la source
1024 convient à une grande variété de circonstances, bien qu'en pratique, vous puissiez constater de meilleures performances avec une taille de mémoire tampon plus ou moins grande.
Cela dépendrait d'un certain nombre de facteurs, notamment la taille des blocs du système de fichiers et le matériel du processeur.
Il est également courant de choisir une puissance de 2 pour la taille de la mémoire tampon, car la plupart du matériel sous-jacent est structuré avec des blocs de fichiers et des tailles de cache d'une puissance de 2. Les classes Buffered vous permettent de spécifier la taille de la mémoire tampon dans le constructeur. Si aucun n'est fourni, ils utilisent une valeur par défaut, qui est une puissance de 2 dans la plupart des JVM.
Quelle que soit la taille de la mémoire tampon que vous choisissez, la plus grande augmentation des performances que vous constaterez est le passage d'un accès aux fichiers sans tampon à un accès aux fichiers tamponnés. L'ajustement de la taille de la mémoire tampon peut améliorer légèrement les performances, mais à moins que vous n'utilisiez une taille de mémoire tampon extrêmement petite ou extrêmement grande, il est peu probable qu'il ait un impact significatif.
la source