1. 程式人生 > 實用技巧 >EhCache、GuavaCache和Caffeine之間的效能比較

EhCache、GuavaCache和Caffeine之間的效能比較

使用JMH實際測試EhCache、GuavaCache和Caffeine之間的效能

測試程式碼

EhCache
@BenchmarkMode({Mode.AverageTime}) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations
=3, time = 5, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations=5,time = 1,timeUnit = TimeUnit.SECONDS) @Threads(8) @Fork(3) @State(Scope.Thread)
public class EhCacheTest { private static CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .build(true); private static Cache<String, String> cache = cacheManager.createCache("myCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.
class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, MemoryUnit.MB)) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(1L))).build()); static { cache.put("test","test"); } @Benchmark public void
test(){ cache.get("test"); } }
Guava Cache

@BenchmarkMode({Mode.AverageTime}) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations
=3, time = 5, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations=5,time = 1,timeUnit = TimeUnit.SECONDS) @Threads(8) @Fork(3) @State(Scope.Thread) public class GuavaTest { private static Cache<String,String> cache = CacheBuilder.newBuilder() .maximumSize(100) .expireAfterWrite(1,TimeUnit.SECONDS) .build(); static { cache.put("test","test"); } @Benchmark public void test(){ cache.getIfPresent("test"); } }
Caffeine

@BenchmarkMode({Mode.AverageTime}) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations
=3, time = 5, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations=5,time = 1,timeUnit = TimeUnit.SECONDS) @Threads(8) @Fork(3) @State(Scope.Thread) public class CaffeineTest { private static Cache<String,String> cache = Caffeine.newBuilder() .maximumSize(100) .expireAfterWrite(1,TimeUnit.SECONDS) .build(); static { cache.put("test","test"); } @Benchmark public void test(){ cache.getIfPresent("test"); } }

說明,實際測試程式碼共有六種情況(其實還有別的情況,不加任何引數使Caffeine使用UnboundedLocalCache,效能應該還會改變,大家如果有興趣可以自己嘗試)

直接放結果

  • 奇特的地方
    • 在加過期時間的情況下三個快取方案的效能均有所提升
    • Guava不加過期時間的情況下高併發會OOM
    • EhCache在加過期時間的情況下竟然比Guava的效能要好
    • Caffeine讀比寫的效能要高很多

總結

  • Guava使用jdk的Queue記錄快取的寫讀情況,導致OOM;而Caffeine使用Disruptor的RingBuffer資料結構記錄
  • Caffeine對寫的所有執行緒共用一個RingBuffer;而對讀的每個執行緒維護一個RingBuffer
  • 使用Caffeine是你不會後悔的選擇
  • 可參考Caffeine