我创建了一个WPF应用程序,它将物理设备(硬盘,USB大容量存储)读取到文件中。我为HD提供高达75-80 MB / s的速度,为USB提供高达20-25 MB的速度。我想动态添加图像的MD5和SHA1散列。基本上我从磁盘读取了128个扇区(64Kb)的块,我使用两个algos对它进行散列,然后将块写入另一个文件。
这两个哈希函数似乎是一个巨大的瓶颈。 Usb的速度降至5 Mb / s,HD的速度降至20 Mb / s。
所以我想把哈希代码放在另一个线程中。因此,一个线程读取块并将值放入FIFO列表(使用List制作)。然后另一个线程弹出一个块并且讨厌它。 问题是从磁盘读取的线程比散列读取的速度快,并且List将以指数方式增长。所以我对1024个块的列表进行了限制。当第一个线程看到列表有1024个或更多块时,它会一直休眠,直到达到512 ...
这似乎适用于前几秒钟。我为Usb获得了19 Mb / s。但稍后,它往往会再次变慢。我想它填满了列表,它正在等待它有一些空间......
也许我的哈希功能很慢?我复制了我在网上发现的第一个...... 如何提高申请速度?
由于
答案 0 :(得分:1)
显然,如果有足够的时间,吞吐量将受限于该过程中较慢部分的性能。使IO与散列异步的优势在于,您可以将两个进程保持在一起,而不是单独使用它们中的任何一个。
很难知道为什么你的哈希是如此慢,但.NET包含MD5和SHA实现,因此你不需要自己编写。
大概如果你有两个线程访问一个List(Queue或ConcurrentQueue可能更好),你就会有一些锁定。你确定你在一个线程上长时间没有锁定,所以另一个线程被阻止了吗?
理想情况下,您需要运行某种类型的分析器,但您可以使用秒表和一些跟踪来计算出发生的情况。
答案 1 :(得分:0)
您可以尝试非加密哈希函数here
它们应该比加密的更快
答案 2 :(得分:0)
这是一个相对简单但有趣的性能难题,不是吗?
对我而言,在哈希算法实现中,你肯定听起来像CPU瓶颈。对于高性能哈希算法,而不是仅仅随机复制某些内容,请使用System.Security.Cryptography
中的标准类,例如SHA1CryptoServiceProvider
和MD5CryptoServiceProvider
。
如果您有多个可用核心,请考虑将散列工作拆分为单独的线程。作为一般经验法则,n
核心 * 使用n+1
个线程;如果您有多线程内核(例如Intel HT),则可能会因使用它们而获得或失去性能。 Task Parallel Library可能help with this,特别是因为输入读取循环可以很容易地重写为iterator。
* 例如,在Pentium IV Prescott芯片上,使用标准比特币客户端中的两个内核会损失大约10%的性能,该客户端主要位于循环运行哈希值中。