我有一个应用程序,它涉及数组的集合,这些数组可能非常大(索引最多为int
的最大值(,但这些数组是惰性的 - 它们的内容是动态计算的,直到请求才真正知道。 数组也是不可变的 - 每个数组的每个元素的值在程序的整个生命周期中都是恒定的。 数组是稀疏的,因为通常只请求所有数组元素的一小部分(数组不包含大的零块,也不是这个意义上的"稀疏"(。
查找(并可能在此过程中计算(数组元素可能很昂贵,因此我想添加一个缓存层。 缓存应实现以下接口:
void point_cache_store (gpointer data, gsize idx, gdouble value);
gdouble point_cache_fetch (gpointer data, gsize idx);
其中data
充当每个数组的唯一句柄(可以有很多这样的数组(。 point_cache_fetch()
应返回具有相同data
和idx
参数传递给point_cache_store()
的value
参数,或者通过返回特殊值DATUM_UNKNOWN_VALUE
来指示缓存未命中(调用方永远不会使用 DATUM_UNKNOWN_VALUE
调用point_cache_store
(。
问题是:如何实现point_cache_fetch()
和point_cache_store()
? (它们目前是无操作存根。
需要考虑的要点:
- 缓存实现必须是线程安全的。 多个线程同时运行,其中任何一个线程都可以使用任何
data
或idx
参数调用point_cache_store()
或point_cache_fetch()
。
缓存 - 确实是一个缓存;
point_cache_fetch()
返回DATUM_UNKNOWN_VALUE
总是可以的,即使它曾经知道这个值。 在这种情况下,调用方将只执行普通查找。 - 请记住,数组是不可变的 - 对于给定的
data
和idx
参数,调用方将始终提供相同的value
参数。
我意识到有很多方法可以做到这一点,并且涉及权衡。 但是,对于这个问题,我将通过一个非常具体的标准来评估答案:它们是否提高了激发该问题的应用程序中的一个特定基准的性能。 如果您想加倍努力并自己运行基准测试,以下是操作方法:
git clone git://github.com/gbenison/starparse
git clone git://github.com/gbenison/burrow-owl.git -b point-cache-base
函数point_cache_fetch()
和point_cache_store()
位于"burrow/spectrum/point_cache.c"中。 相关基准是"基准/b_cache"。
一个"非常大的稀疏惰惰数组"?听起来你需要一个哈希表。
从您的point_cache_fetch
函数原型到您的整个问题,我对缓存的值是双精度数组还是不可变数组感到困惑。
我不打算提供实现,因为这不是一个"编码挑战"网站。您应该尝试查找和重用现有的线程安全哈希表库,并比较它们的性能以满足您的特定需求。