您在谈论的是生命周期依赖链,即一件事依赖于另一件事,可以在其控制之外进行修改。
如果你有一个幂等函数 from a
, b
to c
where, if a
and b
are the same thenc
是相同的,但检查的成本b
很高,那么你要么:
- 接受您有时会使用过时的信息进行操作,并且不总是检查
b
- 尽你最大的努力使检查
b
尽可能快
你不能吃你的蛋糕...
如果您可以基于a
顶部分层附加缓存,那么这会影响初始问题,而不是一点点。如果您选择 1,那么您将拥有您给自己的任何自由,因此可以缓存更多,但必须记住考虑缓存值的有效性b
。如果您选择 2,您仍然必须b
每次都检查,但a
如果b
检查出,则可以依靠缓存。
如果对缓存进行分层,则必须考虑是否由于组合行为而违反了系统的“规则”。
如果你知道它a
总是有效b
的,那么你可以像这样安排你的缓存(伪代码):
private map<b,map<a,c>> cache //
private func realFunction // (a,b) -> c
get(a, b)
{
c result;
map<a,c> endCache;
if (cache[b] expired or not present)
{
remove all b -> * entries in cache;
endCache = new map<a,c>();
add to cache b -> endCache;
}
else
{
endCache = cache[b];
}
if (endCache[a] not present) // important line
{
result = realFunction(a,b);
endCache[a] = result;
}
else
{
result = endCache[a];
}
return result;
}
显然,连续分层(例如x
)是微不足道的,只要在每个阶段新添加的输入的有效性与:和:的a
:b
关系匹配。x
b
x
a
但是,您很可能会得到三个有效性完全独立(或循环)的输入,因此不可能进行分层。这意味着标记为 // 重要的行必须更改为
if (endCache[a]过期或不存在)