6
votes

Conseils maximaux de performance hachage SHA-1 en Java

J'écris une bibliothèque Java qui doit calculer les hachages SHA-1. Au cours d'une tâche commune, la JVM dépense environ 70% de son temps dans Sun.Security.Provider.sha.ImplCompress , 10% dans java.util.zip.infler.inflate , et 2% dans sun.security.provider.bytearrayaccess.b2ibig64 . (Selon NetBeans Profiler.)

Je ne peux pas sembler avoir le droit de recherche sur les mots-clés de la recherche Google pour obtenir des résultats pertinents. Je ne connais pas très bien l'algorithme de hachage Sha-1. Comment puis-je obtenir le plus de performances d'un SHA-1 MessageDigest ? Y a-t-il une certaine taille de morceau que je devrais être digestible ou multiples de certaines tailles que je devrais essayer?

Pour répondre à quelques questions que vous envisagez de demander:

  • Oui, je digestant comme je lisais les fichiers ( MessageDigest.update ), de sorte que les octets ne sont que digérés une fois.
  • Les digests SHA-1 sont utilisés comme checksums, généralement pour des fichiers qui doivent être zlib / gonflés.
  • Non, je ne peux pas utiliser un hachage différent.
  • Oui, je sais que ZLIB utilise déjà des checksums, mais des exigences externes spécifient l'utilisation de hachages SHA-1 en plus de cela. Je ne peux pas trouver une bonne raison pour laquelle (+1 si vous le pouvez): -)

3 commentaires

Si elle est io sur votre ordinateur local qui doit faire ce travail, je suggère d'investir sur un disque SSD, car je soupçonne que la lecture des fichiers du disque dur est un goulot d'étranglement.


J'ai déjà fait le plus que je puisse optimiser les E / S. J'ai déjà examiné diverses optimisations d'Io et le profileur dit que l'IO prend tout autant de temps que de digérer. Je suis sûr que je ne peux pas mieux faire avec io


Java est (était) lent par rapport à C / C ++, mais dans une tâche, c'est un peu plus rapide. Si vous avez accès à une implémentation C / C ++ de votre algorithme, faites une comparaison. Si Java est nettement plus lent, il y a probablement une place d'amélioration, mais s'ils sont presque égaux, il y a probablement de petites chances d'amélioration. (J'ai fait une comparaison avec C et DS lorsque j'ai eu un tas de mathématiques à faire, et il s'est avéré que ma version Java était la plus rapide).


3 Réponses :


0
votes

Avez-vous essayé de changer le traitement du fichier dans un fichier mappé en mémoire? La performance pour ceux qui tendent à être significativement plus rapide que l'IO et Nio ordinaires.


2 commentaires

Les digests SHA-1 sont utilisés comme checksums, généralement pour des fichiers qui doivent être zlib / gonflés. En fait, j'utilise directbytebuffer s car la plupart des fichiers doivent être gonflés avant que la somme de contrôle puisse être calculée. En regardant la pile d'appels du profileur, le moteur de Digest utilise une méthode qui, lorsqu'un tampon envoyé sans tableau (un tampon non-housse), il copie en fait le contenu du tampon direct dans un nouveau tas, Array d'octet primitif. En fait, il optimise même que la mémoire tampon d'octet primitif basée sur le système d'exploitation et la taille du cache CPU L1. En fonction de la JVM.


Ce serait bien si le JRE de Sun a fourni un digesteur qui a fonctionné avec mappébytebuffer . Connaissez-vous celui que je peux distribuer avec la bibliothèque? Il serait encore meilleur si java.util.zip a travaillé avec mappébytebuffer s. Je veux dire, ça marche déjà dans la mémoire natale! Peut-être que je vais mettre dans une rfe ...



2
votes

Peut-être que vous pouvez appeler au code natif écrit en C. Il doit y avoir une tonne de bibliothèques SHA1 super optimisées disponibles.


1 commentaires

EWWW ... cela ressemble à beaucoup de travail. Et je ne sais pas si peut-être que j'ai juste besoin d'envoyer les tampons de taille de bonne taille au digesteur. C'est vraiment ce que j'essaie de le savoir.



1
votes

SHA-1 a une taille de bloc de 64 octets, donc les multiples de ceux-ci sont probablement meilleurs; Sinon, la mise en œuvre devra copier des blocs partiels en tampons.

Êtes-vous en cours d'exécution sur un ordinateur multicœur? Vous pouvez exécuter la décompression zlib et le hachage SHA-1 dans des filets séparés, en utilisant quelque chose comme java.util.concurrent.synchronousqueue pour remettre chaque bloc de 64 octets décompressé de l'autre à l'autre. De cette façon, vous pouvez avoir un nœud de hachage d'un noyau, tandis qu'un autre noyau décompresse le bloc suivant.

(vous pouvez essayer l'un des autres implémentations blockingQingQueue une capacité de stockage, mais je ne pense pas que cela aidait beaucoup. La décompression est beaucoup plus rapide que la hache, donc le zlib. Le fil remplirait rapidement la file d'attente, puis il faudrait attendre de mettre chaque nouveau bloc, comme avec le synchronousqueue .)

Je sais que vous avez dit que vous avez déjà optimisé les E / S, mais utilisez-vous des E / S asynchrones? Pour une performance maximale, vous ne voulez pas que vous ne voulez pas bloquer un bloc et alors Demandez au système d'exploitation de lire le prochain bloc, vous souhaitez demander au système d'exploitation de lire le bloc suivant, puis de hachaîner celui que vous avez déjà. Le disque est occupé à récupérer le prochain. Cependant, le système d'exploitation fait probablement déjà un peu de lecture, donc cela peut ne pas faire une grande différence.

Mais au-delà de tout cela, une fonction de hachage cryptographique est une chose complexe; Il va juste prendre le temps de courir. Peut-être avez-vous besoin d'un ordinateur plus rapide. : -)


4 commentaires

Ce serait bien s'ils avaient utilisé un hachage non cryptographique comme une somme de contrôle au lieu d'un cryptographique sur le dessus du CRC utilisé dans Zlib. Les E / S asynchrones seraient une bonne idée si je ne visais pas la performance de ma bibliothèque, pas vraiment la performance de ce test particulier de la vérification de nombreux fichiers. Il m'a fait penser à la façon dont je peux faire la bibliothèque que je concevons plus de multithread répondant. Je pense avoir été surpris que le calcul des checksums prend plus de temps que le fichier E / S, que les concepteurs des programmes qui utilisent les fichiers que je travaille vient de faire un choix étrange


Eh bien, vraisemblablement, ils veulent la résistance supplémentaire de la collision qu'un hachage cryptographique fournit; Sinon, il n'y aurait aucune valeur ajoutée sur le CRC que Zlib fait déjà.


Et l'accès à un fichier séquentiel n'est pas tout ce qui lent sur les disques durs modernes. J'ai des disques "verts" de 5900 tr / min "qui ont une moyenne de plus de 100 Mo / sec sur tout le lecteur, pic 150 Mo / sec au bord. Par rapport à un algorithme relativement lent comme SHA-1, ce n'est pas mauvais.


Vous penseriez qu'ils veulent la résistance supplémentaire de la collision ... Mais si je disais qu'il n'y a que 57 000 objets uniques? CRC32 ne couvrirait-il pas cela avec des taux de collision super bas?