2013-04-10 3 views
3

Я пытаюсь как можно быстрее получить хэш файла. У меня есть программа, в которой хэшируются большие наборы данных (100 ГБ +), состоящие из произвольных размеров файлов (от нескольких килобайт до 5 ГБ на каждый файл) в любом месте между несколькими файлами до нескольких сотен тысяч файлов.Получить производительность файловой системы/оптимизацию

Программа должна поддерживать все поддерживаемые Java алгоритмы (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512).

В настоящее время я использую:

/** 
* Gets Hash of file. 
* 
* @param file String path + filename of file to get hash. 
* @param hashAlgo Hash algorithm to use. <br/> 
*  Supported algorithms are: <br/> 
*  MD2, MD5 <br/> 
*  SHA-1 <br/> 
*  SHA-256, SHA-384, SHA-512 
* @return String value of hash. (Variable length dependent on hash algorithm used) 
* @throws IOException If file is invalid. 
* @throws HashTypeException If no supported or valid hash algorithm was found. 
*/ 
public String getHash(String file, String hashAlgo) throws IOException, HashTypeException { 
    StringBuffer hexString = null; 
    try { 
     MessageDigest md = MessageDigest.getInstance(validateHashType(hashAlgo)); 
     FileInputStream fis = new FileInputStream(file); 

     byte[] dataBytes = new byte[1024]; 

     int nread = 0; 
     while ((nread = fis.read(dataBytes)) != -1) { 
      md.update(dataBytes, 0, nread); 
     } 
     fis.close(); 
     byte[] mdbytes = md.digest(); 

     hexString = new StringBuffer(); 
     for (int i = 0; i < mdbytes.length; i++) { 
      hexString.append(Integer.toHexString((0xFF & mdbytes[i]))); 
     } 

     return hexString.toString(); 

    } catch (NoSuchAlgorithmException | HashTypeException e) { 
     throw new HashTypeException("Unsuppored Hash Algorithm.", e); 
    } 
} 

Есть ли более оптимизированный способ идти о получении хэш-файлов? Я ищу экстремальную производительность, и я не уверен, что я пошла по этому пути наилучшим образом.

+3

Профилировали ли вы код? Где он проводит большую часть своего времени? – NPE

ответ

5

Я вижу ряд потенциальных улучшений производительности. Один из них - использовать StringBuilder вместо StringBuffer; он совместим с исходным кодом, но более совершенен, потому что он несинхронизирован. Второй (гораздо более важный) будет использовать FileChannel и API java.nio вместо FileInputStream - или, по крайней мере, оберните FileInputStream в BufferedInputStream для оптимизации ввода-вывода.

1

В дополнение к ответу Эрнеста: - MessageDigest.getInstance (validateHashType (hashAlgo)) Я думаю, что это может быть кэшируются в потоке локального HashMap с validateHashType (hashAlgo) в качестве ключа. Создание MessageDigest требует времени, но вы можете его повторно использовать: вызывая метод reset() в начале после получения экземпляра из Map.

См. Javadoc java.lang.ThreadLocal

Смежные вопросы