[英]the fastest way to create checksum for large files in python
我需要跨網絡傳輸大文件,需要每小時為它們創建校驗和。 所以產生校驗和的速度對我來說至關重要。
不知怎的,我不能讓zlib.crc32和zlib.adler32在Windows XP Pro 64bit機器上使用大於4GB的文件。 我懷疑我在這里達到了32位的限制? 使用hashlib.md5我可以得到一個結果,但問題是速度。 為4.8GB文件生成md5大約需要5分鍾。 任務管理器顯示該進程僅使用一個核心。
我的問題是:
PS:我正在開發類似於“資產管理”系統的東西,有點像svn,但資產包括大型壓縮圖像文件。 文件有微小的增量變化。 檢測變化和錯誤檢測需要散列/校驗和。
這是一個算法選擇問題 ,而不是庫/語言選擇問題!
主要有兩點需要考慮:
顯然,第二個問題的答案是“ 允許一些假陰性 ”,因為相對於4Gb消息, 任何 32位散列的可靠性,即使在中等噪聲頻道中,也不會是絕對的。
假設可以通過多線程改進I / O,我們可以選擇不需要對完整消息進行順序掃描的哈希。 相反,我們可以並行處理文件,散列各個部分並組合散列值或附加散列值,以形成更長,更可靠的錯誤檢測設備。
下一步可能是將這種文件處理形式化為有序部分,並將其作為傳輸(在接收者端重新粘合在一起)。 這種方法,以及有關文件生成方式的附加信息(例如,它們可能通過追加,例如日志文件進行排他性修改)甚至可以允許限制所需的哈希計算量。 這種方法增加的復雜性需要加權,以滿足快速CRC計算的需求。
附注:Alder32 不限於消息大小低於特定閾值。 它可能只是zlib API的限制。 (順便說一句,我發現關於zlib.adler32的參考使用了一個緩沖區,而且......在我們的大量消息的上下文中要避免這種方法,支持流式處理:從文件中讀取一些,計算,重復。 。)
首先,任何CRC算法都沒有固有的東西阻止它們處理任意長度的數據(但是,特定的實現可能會施加一個限制)。
但是,在文件同步應用程序中,這可能無關緊要,因為您可能不希望在文件變大時散列整個文件,無論如何都只是塊。 如果散列整個文件,並且每端的散列不同,則必須復制整個文件。 如果您散列固定大小的塊,那么您只需要復制散列已更改的塊。 如果對文件的大多數更改都是本地化的(例如數據庫),那么這可能需要更少的復制(並且它更容易在多個核心上的每個塊計算中傳播)。
至於哈希算法本身,基本的權衡是速度與缺少沖突(兩個不同的數據塊產生相同的哈希)。 CRC-32速度很快,但只有2 ^ 32個唯一值,可能會出現沖突。 MD5要慢得多,但是有2 ^ 128個唯一值,因此幾乎從未見過碰撞(但理論上仍然可能)。 較大的哈希值(SHA1,SHA256,...)具有更多獨特的值,但速度更慢:我懷疑你需要它們:你擔心意外碰撞,不像數字簽名應用程序,你有意擔心(惡意的設計碰撞。
聽起來你正在嘗試做一些與rsync實用程序非常相似的事情。 你能用到rsync嗎?
您可能在XP中遇到文件的大小限制。 64位為您提供更多的尋址空間(每個應用程序移除2GB(左右)尋址空間),但可能對文件大小問題沒有任何作用。
由於MD5的本質,你不可能使用多個核心來計算大文件的MD5哈希:它希望消息以塊的形式分解並以嚴格的順序輸入散列函數。 但是,您可以使用一個線程將文件讀入內部隊列,然后在單獨的線程中計算哈希值。 我不認為這會給你帶來任何顯着的性能提升。
處理大文件需要這么長時間的事實可能是由於“無緩沖”讀取。 嘗試一次讀取16 Kb,然后將內容以塊的形式提供給散列函數。
md5本身不能並行運行。 但是你可以在部分(並行)中md5文件,並獲取哈希列表的md5。
但是,假設散列不受IO限制,我懷疑它是。 正如Anton Gogolev建議的那樣 - 確保你正在有效地閱讀文件(以2個大塊的力量)。 完成后,請確保文件沒有碎片。
對於新項目,還應選擇sha256之類的散列而不是md5。
對於4Gb文件,zlib校驗和是否比md5快得多?
你有沒有試過crc-generator模塊?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.