
EDIT: Ab und zu bekomme ich einen IMA bei "WaitSemaphore(\doneSema)"
Code: Alles auswählen
EnableExplicit
Define *Buffer, iRead, x, sfile.s, CRC$, MD5$, SHA1$
#Buffersize = 8192
Prototype Aufgabe(*buffer, bufferSize.i, iBlock.i)
UseCRC32Fingerprint()
UseMD5Fingerprint()
UseSHA1Fingerprint()
Structure Block
*buffer ; Pointer zum Puffer selbst
size.i ; Größe des Puffers
iBlock.i ; Nummer des Blocks
waitSema.i ; Semaphore um auf Befüllen den Blockes zu warten
doneSema.i ; Semaphore um auf Beendigung der Verarbeitung zu warten
allDoneSema.i ;
stop.i ; #True, wenn der Thread sich beenden soll
List threads.i()
cThreads.i ; Anzahl der Threads
EndStructure
Procedure.i newBlock()
Protected *block.Block = AllocateStructure(Block)
With *block
\waitSema = CreateSemaphore()
\doneSema = CreateSemaphore()
\allDoneSema = CreateSemaphore()
EndWith
ProcedureReturn *block
EndProcedure
Structure ThreadData
*block.Block
aufgabe.Aufgabe
EndStructure
Procedure AufgabeThread(*data.ThreadData)
With *data\block
Repeat
; Warte bis ein neuer Block da ist
WaitSemaphore(\waitSema)
If \stop
Break
EndIf
; Führe die Aufgabe auf dem Block aus
*data\aufgabe(\buffer, \size, \iBlock)
; Melde dem Hauptthread, dass du fertig bist
SignalSemaphore(\doneSema)
; Warte auf den Hauptthread, der dir mitteilt, das alle anderen Threads auch fertig sind
WaitSemaphore(\allDoneSema)
ForEver
EndWith
FreeStructure(*data)
EndProcedure
Procedure.i addThread(*block.Block, aufgabe.Aufgabe)
Protected thread.i
Protected *threadData.ThreadData = AllocateStructure(ThreadData)
If Not *threadData
ProcedureReturn #False
EndIf
With *block
*threadData\block = *block
*threadData\aufgabe = aufgabe
If AddElement(\threads())
\threads() = CreateThread(@AufgabeThread(), *threadData)
If Not \threads()
FreeStructure(*threadData)
DeleteElement(\threads())
EndIf
Else
FreeStructure(*threadData)
ProcedureReturn #False
EndIf
\cThreads = ListSize(\threads())
EndWith
ProcedureReturn #True
EndProcedure
Procedure.i processBlock(*block.Block, *buffer, bufferSize.i, iBlock.i)
Protected i.i
With *block
\buffer = *buffer
\size = bufferSize
\iBlock = iBlock
; Sage allen Threads, dass sie ihre Arbeit beginnen sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte, bis alle Threads fertig sind
For i = 1 To \cThreads
WaitSemaphore(\doneSema)
Next
; Melde allen Threads, das nun alle fertig sind und auf neue Arbeit warten können.
For i = 1 To \cThreads
SignalSemaphore(\allDoneSema)
Next
EndWith
EndProcedure
Procedure.i destroyBlock(*block.Block)
Protected i
With *block
\stop = #True
; Sage allen Threads, dass sie sich beenden sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte auf Beendigung der Threads
ForEach \threads()
WaitThread(\threads())
Next
FreeSemaphore(\waitSema)
FreeSemaphore(\doneSema)
FreeSemaphore(\allDoneSema)
EndWith
FreeStructure(*block)
EndProcedure
; ============== Hauptprogramm ===============
Procedure Aufgabe1(*Buffer, BufferSize, iBlock)
;Debug "Aufgabe1 bearbeitet Block: " + iBlock + " "
AddFingerprintBuffer(0, *Buffer, BufferSize)
EndProcedure
Procedure Aufgabe2(*Buffer, BufferSize, iBlock)
;Debug "Aufgabe2 bearbeitet Block: " + iBlock
AddFingerprintBuffer(1, *Buffer, BufferSize)
EndProcedure
Procedure Aufgabe3(*Buffer, BufferSize, iBlock)
;Debug "Aufgabe3 bearbeitet Block: " + iBlock
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Define.Block *block = newBlock()
StartFingerprint(0, #PB_Cipher_CRC32)
StartFingerprint(1, #PB_Cipher_MD5)
StartFingerprint(2, #PB_Cipher_SHA1)
addThread(*block, @Aufgabe1())
addThread(*block, @Aufgabe2())
addThread(*block, @Aufgabe3())
*buffer = AllocateMemory(#Buffersize)
If Not *buffer
End
EndIf
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
sfile = #PB_Compiler_Home + "PureBasic.exe"
CompilerDefault
sfile = #PB_Compiler_Home + "compilers/PureBasic"
CompilerEndSelect
If ReadFile(0, sfile)
While Not Eof(0)
iRead = ReadData(0, *buffer, #Buffersize)
x + 1
processBlock(*block, *buffer, iRead, x)
;Debug "============================"
Wend
CloseFile(0)
EndIf
FreeMemory(*buffer)
destroyBlock(*block)
Debug "Checksum of file: " + sfile + #CRLF$
CRC$ = FinishFingerprint(0) ; finish calculation
Debug "CRC32 checksum" + #TAB$ + " = " + CRC$
MD5$ = FinishFingerprint(1) ; finish calculation
Debug "MD5 checksum" + #TAB$ + " = " + MD5$
SHA1$ = FinishFingerprint(2) ; finish calculation
Debug "SHA1 checksum" + #TAB$ + " = " + SHA1$
Code: Alles auswählen
EnableExplicit
Define *Buffer, iRead, x, sfile.s, CRC$, MD5$, SHA1$, SHA2$, SHA3$
#Buffersize = 8192 * 1024
Prototype Aufgabe(*buffer, bufferSize.i, iBlock.i)
UseCRC32Fingerprint()
UseMD5Fingerprint()
UseSHA1Fingerprint()
UseSHA2Fingerprint()
UseSHA3Fingerprint()
Structure Block
*buffer ; Pointer zum Puffer selbst
size.i ; Größe des Puffers
iBlock.i ; Nummer des Blocks
waitSema.i ; Semaphore um auf Befüllen den Blockes zu warten
doneSema.i ; Semaphore um auf Beendigung der Verarbeitung zu warten
allDoneSema.i ;
stop.i ; #True, wenn der Thread sich beenden soll
List threads.i()
cThreads.i ; Anzahl der Threads
EndStructure
Procedure.i newBlock()
Protected *block.Block = AllocateStructure(Block)
With *block
\waitSema = CreateSemaphore()
\doneSema = CreateSemaphore()
\allDoneSema = CreateSemaphore()
EndWith
ProcedureReturn *block
EndProcedure
Structure ThreadData
*block.Block
aufgabe.Aufgabe
EndStructure
Procedure AufgabeThread(*data.ThreadData)
With *data\block
Repeat
; Warte bis ein neuer Block da ist
WaitSemaphore(\waitSema)
If \stop
Break
EndIf
; Führe die Aufgabe auf dem Block aus
*data\aufgabe(\buffer, \size, \iBlock)
; Melde dem Hauptthread, dass du fertig bist
SignalSemaphore(\doneSema)
; Warte auf den Hauptthread, der dir mitteilt, das alle anderen Threads auch fertig sind
WaitSemaphore(\allDoneSema)
ForEver
EndWith
FreeStructure(*data)
EndProcedure
Procedure.i addThread(*block.Block, aufgabe.Aufgabe)
Protected thread.i
Protected *threadData.ThreadData = AllocateStructure(ThreadData)
If Not *threadData
ProcedureReturn #False
EndIf
With *block
*threadData\block = *block
*threadData\aufgabe = aufgabe
If AddElement(\threads())
\threads() = CreateThread(@AufgabeThread(), *threadData)
If Not \threads()
FreeStructure(*threadData)
DeleteElement(\threads())
EndIf
Else
FreeStructure(*threadData)
ProcedureReturn #False
EndIf
\cThreads = ListSize(\threads())
EndWith
ProcedureReturn #True
EndProcedure
Procedure.i processBlock(*block.Block, *buffer, bufferSize.i, iBlock.i)
Protected i.i
With *block
\buffer = *buffer
\size = bufferSize
\iBlock = iBlock
; Sage allen Threads, dass sie ihre Arbeit beginnen sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte, bis alle Threads fertig sind
For i = 1 To \cThreads
WaitSemaphore(\doneSema)
Next
; Melde allen Threads, das nun alle fertig sind und auf neue Arbeit warten können.
For i = 1 To \cThreads
SignalSemaphore(\allDoneSema)
Next
EndWith
EndProcedure
Procedure.i destroyBlock(*block.Block)
Protected i
With *block
\stop = #True
; Sage allen Threads, dass sie sich beenden sollen
For i = 1 To \cThreads
SignalSemaphore(\waitSema)
Next
; Warte auf Beendigung der Threads
ForEach \threads()
WaitThread(\threads())
Next
FreeSemaphore(\waitSema)
FreeSemaphore(\doneSema)
FreeSemaphore(\allDoneSema)
EndWith
FreeStructure(*block)
EndProcedure
; ============== Hauptprogramm ===============
Procedure HashCRC32(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(0, *Buffer, BufferSize)
EndProcedure
Procedure HashMD5(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(1, *Buffer, BufferSize)
EndProcedure
Procedure HashSHA1(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Procedure HashSHA2(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Procedure HashSHA3(*Buffer, BufferSize, iBlock)
AddFingerprintBuffer(2, *Buffer, BufferSize)
EndProcedure
Define.Block *block = newBlock()
StartFingerprint(0, #PB_Cipher_CRC32)
StartFingerprint(1, #PB_Cipher_MD5)
StartFingerprint(2, #PB_Cipher_SHA1)
StartFingerprint(3, #PB_Cipher_SHA2, 512)
StartFingerprint(4, #PB_Cipher_SHA3, 512)
addThread(*block, @HashCRC32())
addThread(*block, @HashMD5())
addThread(*block, @HashSHA1())
addThread(*block, @HashSHA2())
addThread(*block, @HashSHA3())
*buffer = AllocateMemory(#Buffersize)
If Not *buffer
End
EndIf
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
sfile = #PB_Compiler_Home + "PureBasic.exe"
CompilerDefault
sfile = #PB_Compiler_Home + "compilers/PureBasic"
CompilerEndSelect
sfile = "/home/nicolas/Videos/MVI_7857.MOV"
Define time.i = ElapsedMilliseconds()
If ReadFile(0, sfile)
While Not Eof(0)
iRead = ReadData(0, *buffer, #Buffersize)
x + 1
processBlock(*block, *buffer, iRead, x)
Wend
CloseFile(0)
EndIf
FreeMemory(*buffer)
destroyBlock(*block)
CRC$ = FinishFingerprint(0)
MD5$ = FinishFingerprint(1)
SHA1$ = FinishFingerprint(2)
SHA2$ = FinishFingerprint(3)
SHA3$ = FinishFingerprint(4)
time = ElapsedMilliseconds() - time
Define.s result
result = "Checksum of file: " + sfile + #CRLF$ +
"CRC32 checksum" + #TAB$ + " = " + CRC$ + #CRLF$ +
"MD5 checksum" + #TAB$ + " = " + MD5$ + #CRLF$ +
"SHA1 checksum" + #TAB$ + " = " + SHA1$ + #CRLF$ +
"SHA2 checksum" + #TAB$ + " = " + SHA2$ + #CRLF$ +
"SHA3 checksum" + #TAB$ + " = " + SHA3$ + #CRLF$ +
"Time: " + StrD(time / 1000.0, 3) + " s"
SetClipboardText(result)
MessageRequester("Checksums", result)
es kommt halt darauf an, wozu du den Hash benutzen willst. Für Passwörter ist das klar. Wenn es aber bspw. darum geht, Übertragungsfehler rauszufinden, dürfte CRC32 deutlich praktischer sein.NicTheQuick hat geschrieben:Normalerweise geht es hier auch nicht darum, was der schnellste Hash ist, sondern wie kryptographisch sicher der Hash ist.
Aber um deine Frage zu beantworten: CRC32 ist am schnellsten.