Pat*_*k M 8 java performance caching guava
显然,正确的答案是"基准测试并找出答案",但本着互联网的精神,我希望有人能为我完成这项工作.
我非常喜欢Guava用于Web服务的缓存库.然而,他们的文档在这一点上相当模糊.
recordStats
public CacheBuilder<K,V> recordStats()
启用CacheStats缓存操作期间的累积.如果不这样Cache.stats(),所有统计数据都将返回零.请注意,记录统计信息需要对每个操作执行簿记,因此会对高速缓存操作造成性能损失.从:
12.0(之前,统计数据收集是自动的)
来自JavaDocs CacheBuilder.recordStats().
我很好奇性能惩罚的严重程度是否由任何人记录,基准或停球.我认为它应该是非常小的,每次操作的纳秒数量级.缓存操作本身已经同步 - 读取不会锁定或阻塞,但写入会获取锁定 - 因此不需要额外的锁定或并发来修改统计信息.这应该限制为每个缓存访问的一些额外的增量操作.
它的另一面可能Cache.stats()是被称为惩罚.我计划通过Codahale MetricsRegistry和Graphite服务器将统计信息暴露给持久记录.净效应是定期检索统计数据,因此如果检索有任何阻塞行为,那可能会很糟糕.
让我们来看看源代码:
CacheBuilder.recordStats()?CacheBuilder定义了一个no-op StatsCounter实现NULL_STATS_COUNTER,这是默认使用的.如果你打电话,.recordStats()它会替换为SimpleStatsCounter有六个LongAddable字段(通常是一个,LongAdder但AtomicLong如果它不能使用,则会回落到LongAdder它跟踪的每个统计数据).
Cache?对于标准LocalCache(您从中得到的CacheBuilder.build()或CacheBuilder.build(CacheLoader)),它StatsCounter 在构造期间构造所需的实例.每个Segment的Cache同样得到自己的实例相同的StatsCounter类型.其他Cache实现可以选择使用a,SimpleStatsCounter如果他们愿意,或提供他们自己的行为(例如,无操作实现).
Cache?每次调用LocalCache都会影响其中一个统计信息调用相关StatsCounter.record*()方法,这反过来会导致支持的原子增量或添加LongAddable. LongAdder记录的速度明显快于AtomicLong,所以就像你说的那样,这应该是很难注意到的.虽然在无操作的情况下,StatsRecorderJIT可以record*()完全优化掉呼叫,这可能会随着时间的推移而显着.但决定不在此基础上追踪统计数据肯定会过早优化.
当你打电话Cache.stats()的StatsCounterS为Cache和所有Segments都聚集在一起,在一个新的StatsCounter和将结果返回给你.这意味着将有最小的阻止; 每个字段只需要读取一次,并且没有外部同步或锁定.这确实意味着技术上存在竞争条件(可以在聚合的中途访问一个分段),但实际上这是无关紧要的.
CacheBuilder.recordStats()对于任何Cache对监控感兴趣的人,您应该感觉很舒服,并且Cache.stats()尽可能频繁地打电话.内存开销大致保持不变,速度开销可以忽略不计(并且比您可能实现的任何类似监控更快),因为争用开销也是如此Cache.stats().
显然,一个专门的线程除了调用Cache.stats()循环之外什么都不做会引起一些争用,但这很愚蠢.任何类型的定期访问都将被忽视.
| 归档时间: |
|
| 查看次数: |
2481 次 |
| 最近记录: |