2010-05-01 6 views
9

현재 약 15 개의 URL을 실행하고 MD5 해시를 확인하려면 md5_file()을 사용합니다. 내가 이것을 더 빨리 만들 수있는 방법이 있습니까? 그것들 모두를 실행하는 데 너무 오래 걸립니다.md5_file()을 더 빠르게 만드는 방법은 무엇입니까?

+0

"15 개의 URL로 실행"은 15 개의 다른 URL이있는 루프에서 'md5_file ('http : //some.url/foo ')'과 같은 의미입니까? 그 "파일"은 얼마나 큰가요? – VolkerK

+0

네, 바로 그 것입니다. MySQL 데이터베이스에서 가져온 다음 md5_file ($ result) 루프에서 실행합니다. 파일은 매우 작으며 실제로는 디스플레이 출력이없고 UI도없고 볼 때 빈 페이지 만 나타납니다. – 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. 다운로드를 병렬화하면 여기에서 큰 이길 수 있습니다. 'md5sum' CLI 명령 (예 :'exec ('bash -c "md5sum file1> file1.md5 &"')')을 사용하거나 PHP의 pcntl_fork()와 같은 것을 사용하여 실제로 md5 부분을 병렬 처리 할 수 ​​있습니다. md5_sum()에 대한 여러 호출을 포크합니다. 이 두 가지 모두 단점이 있지만 적절한 상황에서는 최선의 방법 일 수 있습니다. –

+0

그리고 콜백이 실행되는 동안 실제로 다운로드가 계속되는지 여부도 테스트하지 못했음을 인정해야합니다. 그러나 데이터 부분이 작기 때문에 그다지 중요하지 않기를 바랍니다. – VolkerK

0

md5 알고리즘은 얻을 수있는 것보다 훨씬 빠르며, URL을 가져 오는 것은 속도가 매우 빠릅니다 (파일이 거대한 경우 느려지거나 연결 속도가 느린 경우). 그래서 아니야. 더 빨리 할 수는 없습니다.

0

잘 분명히 당신은 그러나, 일부 속도 이득을 얻기 위해 일부 micro-optimizations 또는 코드 리팩토링을 사용할 수 있지만 다시는 내장 함수 md5_file() 속도를 높일 수 없다, 빨리 만들 md5_file()에 아무것도 할 수 없습니다.

+1

... 물론 몇 가지 마이크로 최적화는 런타임의 2 밀리 초를 줄일 수 있습니다. 아마도. 또는 URL을 병렬로 가져 와서 몇 초만 기다릴 수도 있습니다. "마이크로 최적화"는 거의 가치가 없습니다. –

+0

@ 프랭크, 이것은 문제의 코드를 실제로 포함하기 위해 편집 된 질문에 앞서 게시되었습니다 (코드가 추가 될 때까지 기본적으로 md5_file()을 빠르게하는 방법을 묻습니다). –

0

아니요.이 기능이 내장되어 있으므로 더 빨리 만들 방법이 없습니다.

그러나 코드가 MD5 처리 전에 파일을 다운로드하는 경우 다운로드 속도를 최적화하여 최적화 할 수 있습니다. 미리 크기를 알고 있다면 쓰기 전에 ftruncate를 사용하여 파일의 크기를 설정하여 약간의 속도 증가를 볼 수도 있습니다.

또한 파일이 메모리에 저장할 수있을만큼 크기가 작고 메모리에 이미 저장되어있는 경우 (다운로드되었거나 다른 용도로 사용 중이기 때문에) md5을 사용하여 메모리에서 파일을 조작 할 수 있습니다 md5_file이 아니라 디스크에서 다시 읽어야합니다.

0

아마도 일정 기간 동안 동일한 URL을 확인하고 계신 것입니까? 마지막으로 수정 한 URL의 헤더를 확인할 수 있습니까? 검사중인 페이지가 변경되지 않은 경우 MD5를 다시 계산할 필요가 없습니다.

페이지를 비동기 적으로 요청하여 직렬로 처리하지 않고 병렬 처리 할 수 ​​있으므로 처리 속도가 빨라집니다.

0

MD5 알고리즘의 속도는 선형입니다. 입력이 클수록 시간이 오래 걸리므로 파일이 크다면 할 수있는 일은 많지 않습니다.

VolkerK이 이미 제안했듯이 문제는 대부분 md5 해싱이 아니라 네트워크를 통해 파일을 검색하고 읽는 것일 수 있습니다.

0

here을 최적화하는 것이 좋습니다. 이것은 특히 md5_file이 파일을 읽는 큰 파일에 대해 잘 작동 할 것이며이 함수는 각 파일의 두 번째 바이트를 비교하는 것입니다.

0

원하는 것을 설명하면 도움이됩니다. MD5 해시로 파일을 확인하려는 경우 :

Collision attack이 발생하기 쉽지 않으므로 안전한 방법은 아닙니다. 여러 개의 해시 (파일 분할)를 사용하거나 다른 해시 방법을 사용해야합니다.

관련 문제