2010-05-01 5 views
9

Ich verwende derzeit md5_file(), um ungefähr 15 URLs zu durchlaufen und ihre MD5-Hashes zu verifizieren. Gibt es eine Möglichkeit, dass ich das schneller machen kann? Es dauert viel zu lange, um alle zu durchlaufen.Eine Möglichkeit, md5_file() schneller zu machen?

+0

"ungefähr 15 URLs durchlaufen" bedeutet etwas wie 'md5_file ('http: //some.url/foo')' in einer Schleife mit 15 verschiedenen URLs? Wie groß sind diese "Dateien"? – VolkerK

+0

Ja, genau das ist es. Ich ziehe sie aus einer MySQL-Datenbank und führe sie dann in md5_file ($ result) in einer Schleife aus. Die Dateien sind sehr klein und haben tatsächlich keine Bildschirmausgabe, keine Benutzeroberfläche, nur eine leere weiße Seite beim Betrachten. – Rob

+0

Das Problem ist, dass Sie die Hashes nacheinander und nicht parallel berechnen; 'md5_file' ist nicht der Flaschenhals. Auch wird der Hash einer leeren Datei immer gleich sein. – salathe

Antwort

15

Wahrscheinlich machst du es sequentiell gerade jetzt. I.e. Daten holen 1, Daten verarbeiten1, Daten 2 holen, Daten 2 verarbeiten, ... und der Flaschenhals könnte die Datenübertragung sein.
Sie könnten curl_multi_exec() verwenden, um das ein wenig zu parallelisieren. Entweder ein CURLOPT_WRITEFUNCTION registrieren und jeden Datenblock verarbeiten (schwierig, da md5() genau einen Datenblock verarbeitet).
Oder prüfen Sie, ob Curl-Handles bereits fertig sind, und verarbeiten Sie dann die Daten dieses Handles.

bearbeiten: quick & schmutzig Beispiel mit den hash extension (welchen Funktionen für inkrementellen Hashes bereitstellt) und ein 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); 

(nicht die Ergebnisse, obwohl überprüft ... es ist nur ein Ausgangspunkt)

+2

+1. Parallelisierung von Downloads ist wahrscheinlich ein großer Gewinn hier. Du könntest auch den md5-Teil parallelisieren, entweder mit dem 'md5sum' CLI-Befehl (zB' exec ('bash -c "md5sum file1> file1.md5 &' ')'), oder mit etwas wie PHP's pcntl_fork() mehrere Aufrufe an md5_sum() abzweigen. Diese beiden haben ihre Nachteile, aber im richtigen Kontext sind sie vielleicht das Beste. –

+0

Und ich muss zugeben, dass ich nicht einmal getestet habe, ob der Download wirklich fortgesetzt wird, während der Callback ausgeführt wird. Aber da die Datenanteile angeblich klein sind, hoffe ich, dass es (viel) keine Rolle spielt. – VolkerK

0

Der MD5-Algorithmus ist so schnell wie es geht, und das Abrufen von URLs ist so schnell wie es nur geht (langsam, wenn die Dateien riesig sind oder Sie eine langsame Verbindung haben). Also nein. Du kannst es nicht schneller machen.

0

Nun offensichtlich kann man nicht mit md5_file() alles tun, schneller zu machen, können Sie jedoch einige micro-optimizations oder Code Refactoring verwenden, um einige Geschwindigkeitsgewinn zu erhalten, aber wieder können Sie die eingebaute Funktion md5_file() beschleunigen.

+1

... Sicher, ein paar Micro-Optimierungen könnten 2 Millisekunden seiner Laufzeit rasieren. Könnte sein. Oder er könnte einfach die URLs parallel ziehen und ein paar Sekunden sparen. "Mikrooptimierungen" sind fast nie die Mühe wert. –

+0

@Frank, Dies wurde vor der Frage veröffentlicht, die bearbeitet wird, um den fraglichen Code tatsächlich einzuschließen (der, bis Code hinzugefügt wurde, im Grunde gefragt wurde, wie man md5_file() beschleunigt). –

0

Nein. Da dies eine eingebaute Funktion ist, gibt es keine Möglichkeit, es schneller zu machen.

Wenn Ihr Code jedoch Dateien herunterlädt, bevor diese heruntergeladen werden, kann es möglich sein, Ihre Downloads schneller zu optimieren. Sie können auch eine kleine Geschwindigkeitssteigerung feststellen, indem Sie die Größe der Datei (mit ftruncate) vor dem Schreiben einstellen, wenn Sie die Größe im Voraus kennen.

Wenn die Dateien klein genug sind, um im Speicher zu bleiben, und Sie sie bereits im Speicher haben (weil sie heruntergeladen wurden oder für einen anderen Zweck gelesen werden), können Sie verwenden anstelle von md5_file, die es erfordert, dass es erneut von der Festplatte gelesen werden.

0

Vermutlich werden dieselben URLs über einen bestimmten Zeitraum hinweg überprüft? Können Sie die zuletzt geänderten Header für die URL überprüfen? Wenn sich die zu überprüfende Seite nicht geändert hat, ist eine Neuberechnung des MD5 nicht erforderlich.

Sie könnten die Seiten auch asynchron anfordern, damit sie parallel und nicht seriell verarbeitet werden können, was die Geschwindigkeit erhöhen sollte.

0

Die Geschwindigkeit des MD5-Algorithmus ist linear. Je größer die Eingabe ist, desto mehr Zeit wird benötigt. Wenn also die Datei groß ist, können Sie nicht viel tun.

Jetzt, wie VolkerK bereits vorgeschlagen, das Problem ist höchstwahrscheinlich nicht das md5 Hashing sondern das Abrufen und Lesen der Datei über das Netz.

0

Ich sehe einen sehr guten Vorschlag zur Optimierung here. Dies funktioniert besonders gut für große Dateien, wo md5_file die Datei liest und diese Funktion nur das zweite Byte jeder Datei vergleicht.

0

Erklären, was Sie tun möchten, würde helfen. Wenn Sie eine Datei mit ihren MD5-Hashes verifizieren möchten:

Es ist keine sichere Methode, da es anfällig für Collision attack ist. Sie sollten mehrere Hashes verwenden (z. B. indem Sie die Datei aufteilen) oder andere Hash-Methoden verwenden.

Verwandte Themen