Способ сделать md5_file() быстрее?

Я сейчас пользуюсь md5_file() выполнить около 15 URL-адресов и проверить их хеши MD5. Есть ли способ, которым я могу сделать это быстрее? Это занимает слишком много времени, чтобы пройти через все из них.

8 ответов

Решение

Возможно, вы делаете это последовательно прямо сейчас. Т.е. данные 1 выборки, данные 1 процесса, данные 2 выборки, данные 2 процесса... и узким местом могут быть данные.
Вы можете использовать curl_multi_exec(), чтобы немного распараллелить это. Либо зарегистрируйте CURLOPT_WRITEFUNCTION и обработайте каждый фрагмент данных (хитро, поскольку md5() работает только с одним фрагментом данных).
Или проверьте уже готовые маркеры скручивания, а затем обработайте данные этого маркера.

edit: быстрый и грязный пример с использованием расширения хэша (который предоставляет функции для инкрементных хэшей) и закрытие php5.3+:

$urls = array(
  'http://stackru.com/',
  'http://sstatic.net/so/img/logo.png',
  'http://www.gravatar.com/avatar/212151980ba7123c314251b185608b1d?s=128&d=identicon&r=PG',
  'http://de.php.net/images/php.gif'
);

$data = array();
$fnWrite = function($ch, $chunk) use(&$data) {
  foreach( $data as $d ) {
    if ( $ch===$d['curlrc'] ) {
      hash_update($d['hashrc'], $chunk);
    }
  }
};

$mh = curl_multi_init();
foreach($urls as $u) {
  $current = curl_init();
  curl_setopt($current, CURLOPT_URL, $u);
  curl_setopt($current, CURLOPT_RETURNTRANSFER, 0);
  curl_setopt($current, CURLOPT_HEADER, 0);
  curl_setopt($current, CURLOPT_WRITEFUNCTION, $fnWrite);
  curl_multi_add_handle($mh, $current);
  $hash = hash_init('md5');
  $data[] = array('url'=>$u, 'curlrc'=>$current, 'hashrc'=>$hash); 
}

$active = null;
//execute the handles
do {
  $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
  if (curl_multi_select($mh) != -1) {
    do {
      $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  }
}

foreach($data as $d) {
  curl_multi_remove_handle($mh, $d['curlrc']);
  echo $d['url'], ': ', hash_final($d['hashrc'], false), "\n";
}
curl_multi_close($mh);

(пока не проверял результаты... это только отправная точка)

Алгоритм md5 работает настолько быстро, насколько это возможно, а получение URL-адресов происходит так же быстро, как и может (медленно, если файлы огромны или у вас медленное соединение). Так что нет. Вы не можете сделать это быстрее.

Я вижу очень хорошее предложение по оптимизации здесь. Это будет хорошо работать, особенно для больших файлов, где md5_file читает файл, а эта функция просто сравнивает второй байт каждого файла.

Предположительно, вы проверяете одни и те же URL-адреса в течение определенного периода времени? Не могли бы вы проверить последние измененные заголовки для URL? Если проверяемая страница не изменилась, то не было бы необходимости пересчитывать MD5.

Вы также можете запросить страницы асинхронно, чтобы они могли обрабатываться параллельно, а не последовательно, что должно ускорить его.

Скорость алгоритма MD5 линейна. Чем больше ввод, тем больше времени потребуется, поэтому, если файл большой, на самом деле мало что можно сделать.

Теперь, как уже предположил VolkerK, проблема, скорее всего, не в хешировании md5, а в извлечении и чтении файла по сети.

Нет. Так как это встроенная функция, нет способа сделать это быстрее.

Но если ваш код загружает файлы до MD5, возможно, вы сможете оптимизировать загрузку, чтобы быстрее. Вы также можете увидеть небольшое увеличение скорости, установив размер файла (используя ftruncate) перед записью, если вы знаете размер заранее.

Кроме того, если файлы достаточно малы, чтобы их можно было хранить в памяти, и у вас уже есть они в памяти (потому что они были загружены или читаются для каких-то других целей), тогда вы можете использовать md5 работать с ним в памяти, а не md5_file который требует, чтобы это было прочитано снова с диска.

Ну, очевидно, вы ничего не можете сделать с md5_file() однако, чтобы сделать быстрее, вы можете использовать некоторые микрооптимизации или ре-факторинг кода, чтобы получить некоторое увеличение скорости, но опять же вы не можете ускорить встроенную функцию md5_file(),

Объяснение того, что вы хотите сделать, помогло бы. Если вы хотите проверить файл с их MD5-хешами:

Это не безопасный метод, так как он подвержен атаке Collision. Вы должны использовать несколько хешей (возможно, разделив файл) или используя другие методы хеширования.

Другие вопросы по тегам