2010-05-01 3 views
9

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

+0

«Пропустить около 15 URL-адресов» означает нечто вроде 'md5_file ('http: //some.url/foo')' в цикле с 15 разными URL-адресами? Насколько велики эти «файлы»? – VolkerK

+0

Да, это точно. Я вытаскиваю их из базы данных MySQL, а затем запускаю их в md5_file ($ result) в цикле. Файлы ОЧЕНЬ малы и фактически не имеют вывода на дисплей, нет пользовательского интерфейса, только пустая белая страница при просмотре – Rob

+0

Проблема в том, что вы вычисляете хэши последовательно, а не параллельно; 'md5_file' не является узким местом. Кроме того, конечно, хэш пустого файла всегда будет таким же. – salathe

ответ

15

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

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

$urls = array(
    'http://stackoverflow.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); 

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

+2

+1. Параллельное скачивание, вероятно, огромная победа здесь. Вы также можете распараллелить часть md5, используя команду 'md5sum' CLI (например,' exec ('bash -c "md5sum file1> file1.md5 &"')) или используя что-то вроде PHP pcntl_fork() для разворачивания нескольких вызовов в md5_sum(). У обоих есть свои недостатки, но в правильном контексте они могут быть лучше всего. –

+0

И я должен признать, что я даже не проверял, действительно ли загрузка действительно продолжается во время выполнения обратного вызова. Но поскольку части данных предположительно малы, я надеюсь, что это не имеет значения (много). – VolkerK

0

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

0

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

+1

... Несомненно, несколько микро-оптимизаций могут брить 2 миллисекунды его времени выполнения. Может быть. Или он мог просто потянуть URL-адреса параллельно и сэкономить несколько секунд. «Микро-оптимизация» почти никогда не стоит усилий. –

+0

@Frank. Это было опубликовано до того, как вопрос был отредактирован, чтобы фактически включить данный код (который, пока код не был добавлен, в основном спросил, как ускорить md5_file()). –

0

Нет. Поскольку это встроенная функция, нет возможности ускорить ее работу.

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

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

0

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

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

0

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

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

0

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

0

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

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

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