ehcache / ehcache3

Ehcache 3.x line
http://www.ehcache.org
Apache License 2.0
2k stars 578 forks source link

[Bug] ehcache can't support max size with heap? #3214

Closed zilong closed 6 months ago

zilong commented 6 months ago

@org.junit.Test public void test0() throws InterruptedException { LocalCacheConfig config = new LocalCacheConfig(); CacheConfiguration<String, String> cacheConfig = CacheConfigurationBuilder .newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .heap(2, EntryUnit.ENTRIES)) .build(); CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true); Cache<String, String> cache = cacheManager.createCache("test", cacheConfig);

    for (int i=0; i<10; i++) {
        String key = "key:" + i;
        cache.put(key , "value:" + i);
        cache.iterator().forEachRemaining((item)-> {
            System.out.println(item.getKey() + " " + item.getValue());
        });
        System.out.println("----------------");
        if (cache.get(key) == null) {
            System.err.println("hit bug: " + i + "=>" + cache.get(key));
        }

    }
}

console:

key:0 value:0

key:1 value:1 key:0 value:0

key:1 value:1 key:0 value:0

hit bug: 2=>null key:3 value:3 key:0 value:0

key:4 value:4 key:3 value:3

key:5 value:5 key:3 value:3

key:5 value:5 key:3 value:3

hit bug: 6=>null key:5 value:5 key:3 value:3

hit bug: 7=>null key:5 value:5 key:3 value:3

hit bug: 8=>null key:3 value:3 key:9 value:9

chrisdennis commented 6 months ago

Capacity enforcement is working correctly. There is no guarantee that the element evicted to satisfy the capacity constraints won't be the element put, and with very small cache capacities this can and does happen. The following test correctly captures the assertions that can be made here:

@Test
public void testHeapCapacityEnforcement() {
  try (CacheManager cacheManager = newCacheManagerBuilder().build(true)) {
    Cache<String, String> cache = cacheManager.createCache("test",
      newCacheConfigurationBuilder(String.class, String.class, heap(2)));

    for (int i = 0; i < 10; i++) {
      cache.put("key:" + i, "value:" + i);

      assertThat(cache, is(iterableWithSize(lessThanOrEqualTo(2))));
      for (int j = 0; j <= i; j++) {
        assertThat(cache.get("key:" + j), anyOf(nullValue(), equalTo("value:" + j)));
      }
    }
  }
}