Seite 1 von 1

Performance: hash, md5, sha, hmac...

Verfasst: Donnerstag 28. Juni 2007, 08:36
von jens
Ich wollte mal wissen, wie schnell die verschiedenen Hash Funktionen in Python v2.4 sind.
hmac kann man eigentlich ganz vergessen. Der ist so langsam das es keinen Sinn macht, diesen mit zu testen. Ansonsten dauert es ewig oder man muß die loop Anzahl so niedrig einstellen, das die anderen Tests keinen Sinn machen. Probiert es mal selber:

Code: Alles auswählen

import timeit, os, string

loop = 500000

TEST_STRING = string.ascii_letters + string.digits

tests = (
    ("hash('%s')" % TEST_STRING, ""),
    ("md5.new('%s').hexdigest()" % TEST_STRING, "import md5"),
    ("sha.new('%s').hexdigest()" % TEST_STRING, "import sha"),
    #~ ("hmac.new('%s').hexdigest()" % TEST_STRING, "import hmac"),
)

for no, test in enumerate(tests):
    print "%s - %s" % (no+1, test[0])

    test = timeit.Timer(test[0], test[1])
    print "%.2f" % test.timeit(number=loop)

    print
Ergebnis:
1 - hash('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
Test: 0.09

2 - md5.new('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789').hexdigest()
Test: 0.83

3 - sha.new('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789').hexdigest()
Test: 0.99
Die Python hash() Funktion ist also ungeschlagen. Leider dürften damit aber recht schnell Kollisionen auftreten ;(

Verfasst: Donnerstag 28. Juni 2007, 16:57
von veers
Es scheint du hast nicht ganz verstanden was ein hmac ist,
Sieh dir mal das an:
http://de.wikipedia.org/wiki/HMAC

Und zu Python Hash Funktion, ich nehme mal stark an das diese nicht entwickelt wurde um Kryptographisch brauchbar zu sein.

Verfasst: Donnerstag 28. Juni 2007, 18:31
von BlackJack
@jens: Der erste Test misst nicht Berechnung des Zeichenketten-Hashwertes, sondern nur wie schnell eine Methode aufgerufen werden kann, die eine Konstante zurück gibt. `hash()` ruft `str.__hash__()` auf und da Zeichenketten immutabel sind, wird deren Hashwert *einmal* beim erzeugen der Zeichenkette, hier also beim kompilieren, berechnet.

Verfasst: Donnerstag 28. Juni 2007, 19:24
von jens
@veers: Ehrlich gesagt, hab ich mir wirklich nicht hmac angesehen :oops:

@BlackJack: Hm. Dann müsste ich den Test-String dynamisch erzeugen... Ob es reicht ein eval() zu machen ? Naja... Egal...

Verfasst: Montag 29. Oktober 2007, 19:10
von Leonidas
Du kannst ja noch ``binascii.crc32`` benchmarken, für einige Anwenungsfälle ist das auch brauchbar.

Verfasst: Dienstag 30. Oktober 2007, 08:46
von jens
ok, hier:

Code: Alles auswählen

import timeit, os, string

loop = 700000

TEST_STRING = string.ascii_letters + string.digits

tests = (
    ("md5.new('%s').hexdigest()" % TEST_STRING, "import md5"),
    ("sha.new('%s').hexdigest()" % TEST_STRING, "import sha"),
    ("binascii.crc32('%s')" % TEST_STRING, "import binascii"),
)

for no, test in enumerate(tests):
    print "%s - %s" % (no+1, test[0])

    test = timeit.Timer(test[0], test[1])
    print "%.2f" % test.timeit(number=loop)

    print
Ausgaben:
1 - md5.new('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789').hexdigest()
1.18

2 - sha.new('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789').hexdigest()
1.39

3 - binascii.crc32('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
0.57
Also binascii.crc32 ist am schnellsten. Allerdings ist es auch nur eine 32-bit checksum ;)