c - 用于稀疏、惰性、不可变数组的线程安全缓存

标签 c caching immutability glib sparse-array

我有一个应用程序,涉及一个数组集合,这些数组可能非常大(索引最大为 int 的最大值),但它们是惰性 - 它们内容是动态计算的,并且在请求之前实际上是不知道的。数组也是不可变的 - 每个数组的每个元素的值在程序的整个生命周期中都是恒定的。这些数组是稀疏,因为通常只请求所有数组元素的一小部分(数组不包含大块的零,因此在这个意义上不是“稀疏”。)

查找(并可能在过程中计算)数组元素可能会很昂贵,因此我想添加一个缓存层。缓存应该实现以下接口(interface):

void point_cache_store (gpointer data, gsize idx, gdouble value);
gdouble point_cache_fetch (gpointer data, gsize idx);

其中data充当每个数组的唯一句柄(可以有很多这样的数组)。 point_cache_fetch() 应返回传递给 point_cache_store()value 参数,并具有相同的 dataidx 参数,或通过返回特殊值 DATUM_UNKNOWN_VALUE 来指示缓存未命中(调用者永远不会使用 DATUM_UNKNOWN_VALUE 调用 point_cache_store)。

问题是:如何实现 point_cache_fetch()point_cache_store()? (它们目前是无操作 stub 。)

需要考虑的要点:

  • 缓存实现必须是线程安全的。多个线程同时运行,其中任何线程都可以使用任何 dataidx 调用 point_cache_store()point_cache_fetch() > 论据。
  • 缓存确实是一个缓存; point_cache_fetch() 返回 DATUM_UNKNOWN_VALUE 总是可以的,即使它曾经知道该值。在这种情况下,调用者将仅执行普通查找。
  • 请记住,数组是不可变的 - 对于给定的 dataidx 参数,调用者将始终提供相同的 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”中。相关基准是“benchmarks/b_cache”。

最佳答案

“非常大的稀疏惰性数组”?听起来你需要一个 hash table .

从您的 point_cache_fetch 函数原型(prototype)和整个问题中,我对您的缓存值是 double 还是不可变数组感到困惑。

我不会提供实现,因为这不是“编码挑战”网站。您应该尝试查找并重用现有的线程安全哈希表库,并根据您的特定需求比较它们的性能。

关于c - 用于稀疏、惰性、不可变数组的线程安全缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10502580/

相关文章:

java - Spark 使用不可变类和 java (+ lombok) 时出现反序列化错误

.NET:GC 何时运行?内存泄漏?

c - 运行 C 代码时输出错误

c - 通过非特权套接字在应用程序级别获取 ICMP 消息内容

.htaccess - htaccess的缓存和gzip压缩

javascript - 为什么我的 javascript 文件有时压缩有时不压缩?(IIS Gzip 问题)

java - 如何在类中使用 List<String> 元素创建不可变类

c - 为什么这些构造使用增量前和增量后未定义的行为?

c++ - 如何在不需要 LIBCD.lib 的情况下在 Visual Studio 6 中编译 C 项目?

使用 DiskBasedCache 时 Android Volley ListView 图像未加载