2010-12-14 102 views
5

Je profilais mon code qui chargeait un fichier binaire. Le temps de chargement était d'environ 15 secondes.Recherche de la taille optimale pour BufferedInputStream en Java

La majorité de mon temps de chargement provenait des méthodes qui chargeaient des données binaires.

J'ai eu le code suivant pour créer mon DataInputStream:

is = new DataInputStream(
    new GZIPInputStream(
    new FileInputStream("file.bin"))); 

Et je l'ai changé à ceci:

is = new DataInputStream(
    new BufferedInputStream(
    new GZIPInputStream(
    new FileInputStream("file.bin")))); 

Donc, après avoir fait cette petite modification du code de chargement est passé de 15 secondes à 4.

Mais alors j'ai trouvé que BufferedInputStream a deux constructeurs. L'autre constructeur vous permet de définir explicitement la taille de la mémoire tampon.

J'ai deux questions:

  1. Quelle est la taille choisie BufferedInputStream et est-il idéal? Si non, comment puis-je trouver la taille optimale pour le tampon? Devrais-je écrire un petit morceau de code qui fait une recherche binaire?
  2. Est-ce la meilleure façon d'utiliser BufferedInputStream? Je l'avais initialement dans le GZIPInputStream mais il y avait un avantage négligeable. Je suppose que ce que le code fait maintenant est chaque fois que le tampon de fichier doit être rempli, le flux d'entrée GZIP passe à travers et décode x octets (où x est la taille du tampon). Serait-il utile d'omettre le GZIPInputStream entièrement? Ce n'est certainement pas nécessaire, mais la taille de mon fichier est considérablement réduite lors de son utilisation.

Répondre

8

Les deux GZIPInputStream et BufferedInputStream utilisent un tampon interne. C'est pourquoi l'utilisation d'un BufferedInputStream à l'intérieur du GZIPInputStream n'apporte aucun avantage. Le problème avec le GZIPInputStream est qu'il ne tamponne pas la sortie qu'il génère, donc votre version actuelle est beaucoup plus rapide. La taille de mémoire tampon par défaut de BufferedInputStream est de 8 ko, vous pouvez donc essayer d'augmenter ou de diminuer cela pour voir si cela aide. Je doute que le nombre exact compte beaucoup, donc vous pouvez simplement multiplier ou diviser par deux.

Si le fichier est petit, vous pouvez également essayer de le mettre complètement en mémoire tampon. Cela devrait vous donner la meilleure performance en théorie. Vous pouvez également essayer d'augmenter la taille de la mémoire tampon de GZIPInputStream (512 octets par défaut), car cela peut accélérer la lecture à partir du disque.

+0

Je vous suggère d'essayer un tampon de 64 Ko pour le GZIPInputStream lors de la lecture à partir d'un disque. J'utilise 1 Mo, ce qui est probablement plus que nécessaire. ;) –

4
  1. Ne vous embêtez pas avec une recherche binaire codé. Essayez juste quelques valeurs à la main et comparez les temps (vous pouvez faire une recherche binaire manuelle si vous aimez). Vous trouverez probablement qu'une très large gamme de tailles de tampons vous donnera des performances proches de l'optimum, alors choisissez le plus petit qui fait l'affaire.

  2. Ce que vous avez le bon ordre: (. Mais pas la sortie)

    is = new DataInputStream(
        new BufferedInputStream(
        new GZIPInputStream(
        new FileInputStream("file.bin")))); 
    

    Il est inutile de mettre un BufferedInputStream à l'intérieur du GZIPInputStream puisque ces derniers tampons déjà son entrée

    Retrait GZIPInputStream peut être une victoire, mais sera probablement préjudiciable à la performance si les données doivent être lues à partir du disque et ne résident pas dans le cache du système de fichiers. La raison en est que la lecture à partir du disque est très lente et la décompression gzip est très rapide. Par conséquent, il est généralement moins coûteux de lire moins de données à partir du disque et de le décompresser en mémoire que de lire davantage de données à partir du disque.

+0

Merci pour votre avis. – Brad

+0

De rien. J'ai édité la réponse avec un peu plus d'informations. – NPE