在应用程序启动时,我构建了一个图标缓存(24x24 32bbp预乘的argb位图)。此缓存包含大约一千个项目。出于内存和性能方面的原因,我不想在此缓存中多次存储相同的图像。我认为最好的方法是在每个位图进入缓存时创建某种crc,并将新位图与这个crcs列表进行比较。
从仅在内存中加载的位图创建crc的好(快速)方法是什么?
或者我完全走错了道路,是否有更好的方法来构建位图缓存?
答案 0 :(得分:2)
虽然我会回应Hans所说的内容,但我相信你可以做到这一点,但CRC是一个糟糕的算法。
您可以改为创建生成的位图字节的MD5哈希值。根据我的计算,您的图像必须至少为2Kb。要生成一个哈希,你可以在整个位图上计算它,或者你可以偷偷摸摸地在每个 n 字节上做 - 这在哈希方面会更快但在内存使用上可能更重你必须将这些字节提取到一个新的数组中。
如果你要跳过每个第n个字节,我会使用4或2 - 使用4意味着你从每个连续像素中读取一个分量,使用两个意味着你从每个连续像素中读取两个分量。
但是,MD5 非常快,您可能会发现(我会在单元测试中对此进行基准测试)只是在整个位图上进行散列会更快。
唯一的事情是 ,我无法预先知道您是否可以提前检查是否生成给定位图而无需提前知道它的哈希值,你知道哈希的唯一方法是生成它。在这种情况下,您可以将新图像保存出去。图像缓存阵列中的额外元素不会破坏宇宙。
你真正需要能够在这里实际节省空间和启动时间的是在生成图像之前知道它是否会与另一个图像相同。假设这些图像是动态生成的,那么当生成两个相同的图像时,它们是通过相同的方法调用使用相同的参数生成的吗?
如果是这样,您可以改为使用一个或多个哈希码(使用object.GetHashCode()
)为生成图像的方法的MethodInfo
标记每个生成的图像(您可以在方法内部获取该图像)本身通过调用MethodBase.GetCurrentMethod()
,以及传入的每个参数的每个哈希码。该方法的哈希码非常可靠,因为它使用运行时的方法句柄(每个方法都是唯一的) - 唯一的哈希码在64位机器上可能出现压缩,其中句柄为64位,但哈希码为32.但是,实际上这种冲突很少发生,因为您必须在应用程序中有大量代码才能导致两个独立的方法句柄的前32位是相同的。
当然,除非这些参数类型具有良好的哈希码函数,否则各个参数的哈希码的可靠性要差得多。
这个解决方案绝不是完美的(最糟糕的是你仍然会得到一些重复),但我认为它会加快速度。就像我说的那样,它依赖于你的重复图像总是由相同的调用生成。
答案 1 :(得分:1)
CRC具有与任何散列函数相同的缺陷:相等的CRC值不证明图像是相同的。你的程序将随机地,但不经常显示错误的图像。
你还需要别的东西。就像您从中检索位图的文件名一样。