2012-05-04 17 views
7

En la Biblioteca de Guava, estoy confundido acerca de por qué Cache.asMap() no es coherente con Cache.size(), a menos que se llame Cache.cleanUp().Cache.asMap() no es consistente con Cache.size()?

Cache<Object, Object> cache = CacheBuilder.newBuilder() 
      .expireAfterWrite(1, TimeUnit.SECONDS) 
      .build(); 
cache.get(...); 
... 
//After some seconds, all entries are expired. 
//cache.asMap() is EMPTY Map, but cache.size() != 0 

Así que mi pregunta: ¿Es error que Cache.asMap() no es coherente a Cache.size()? Aunque noto el Javadoc de Cache.size() es:

/** 
    * Returns the **approximate** number of entries in this cache. 
    */ 

que sólo puede adivinar que está relacionado con un entorno concurrente. Y qué Cache.cleanUp() hacen exactamente?

Respuesta

13

caché de guayaba está diseñado alrededor de la amortización de bloqueo y el método cleanUp hace que el caché para llegar a un estado coherente. El método Map.size() es una aproximación, pero puede contar entradas pendientes expulsión debido a la expiración o desalojo de referencia. La visibilidad de las aproximaciones en el caché de Guava rara vez son de gran interés para una aplicación, lo que tiende a pensar en un caché como un almacén de datos transitorio. Las diferentes expectativas de una memoria caché desde un Mapa llevaron al método asMap para permitir que la memoria caché se vea como un mapa, pero desfavorece que los desarrolladores lo perciban de esa manera.

Los detalles de implementación de la caché estaba cubierto de la conferencia StrangleLoop 2011 slides. El design document de ConcurrentLinkedHashMap, del que se obtuvo el caché de Guava, también puede ser de interés, pero describe un enfoque ligeramente diferente.

9

Ben dio una buena respuesta de alto nivel. La respuesta de bajo nivel es:

asMap() vistas tienen el lujo de atravesar cada elemento en la memoria caché y, por lo tanto, pueden omitir las entradas no válidas que están pendientes de limpieza. Por otro lado, se espera que size() sea una operación rápida, y sería una tontería atravesar todo el caché solo para obtener una estimación de tamaño más precisa.

Los CacheBuilder javadocs entran en más detalles con respecto a la limpieza que debe suceder en diversas situaciones (como expireAfterWrite, en su caso).

+1

Gracias, Charles! Revisé el código fuente aproximadamente, 'size()' solo resume el conteo de Segment, como mencionaste- "tonto para recorrer todo el caché solo para obtener un estimado de tamaño más preciso" :) ¡Diseño altamente sofisticado! –

Cuestiones relacionadas