2011-04-17 11 views
5

Necesito implementar un caché en java con un tamaño máximo, me gustaría hacerlo utilizando el tamaño real de la caché en la memoria y no el número de elementos en la caché. Este caché básicamente tendrá String como clave y String como valor. Ya he implementado el caché usando la estructura LinkedHashMap de java, pero la pregunta es cómo saber el tamaño real del caché para que pueda adaptar la política para soltar un objeto cuando el tamaño es demasiado grande.LRU byte Cache java

Quería calcularlo utilizando el getObjectSize() del paquete de instrumentación, pero parece que no funciona como se desea.

Cuando obtengoObjectSize (una cadena) cualquiera que sea el tamaño de la cadena, devuelve el mismo tamaño: 32. Supongo que solo está usando el tamaño de referencia de la cadena o algo así y no el contenido. Entonces no sé cómo resolver este problema de manera eficiente.

¿Tiene alguna idea?

¡Muchas gracias!

Respuesta

4

Es posible que desee considerar el uso de Ehcache con memory based cache sizing.

+0

Thx, eso debería hacer el trabajo y probablemente sea mejor que mi memoria caché implementada, supongo. ¿Qué tipo de caché sugerirías? ¿Según el número de entradas o el tamaño de la memoria caché? Sabiendo que se supone que la aplicación debe ejecutarse en un servidor y puede tomar toda la memoria disponible en la máquina. – Abbadon

1

Si sus claves y valores son ambas cadenas, el cálculo es fácil: sobrecarga del objeto + 2 bytes por carácter en las cadenas. En una JVM Sun de 32 bits, son correctos 32 bytes para la sobrecarga.

Hay un par de advertencias: primero, el mapa que usa para mantener el caché agrega su propia sobrecarga. Esto dependerá del tamaño de la tabla hash y del número de entradas en el mapa. Personalmente, simplemente ignoraría todos los gastos generales y basaría el cálculo en las longitudes de las cuerdas.

En segundo lugar, a menos que rastree cadenas por identidad, puede contar demasiado porque la misma cadena se puede almacenar con varias claves. Dado que el seguimiento de cadenas por identidad agregaría aún más sobrecarga, probablemente esto no valga la pena.

Y finalmente: mientras que los cachés de memoria limitada parecen como una buena idea, rara vez lo son. Si conoce su aplicación lo suficientemente bien, debe conocer la longitud promedio de la cadena, y puede controlar la caché en función del número de entradas. Y si no conoce bien su solicitud, es probable que una simple política de vencimiento de LRU lo meta en problemas: una entrada grande puede causar que muchas entradas pequeñas expiren. Y si eso sucede, a menos que el costo de reconstrucción sea proporcional al tamaño, acaba de hacer que su caché sea menos efectiva.

+0

+1 ... Nota adicional: el * "carácter" * es realmente lo que cabe en un char de Java. Si por alguna razón el OP trabaja con muchos caracteres solo disponibles desde Unicode 3.1 y superior, entonces se necesitan dos caracteres * de Java * (porque un solo carácter * de Java * solo puede contener puntos de código Unicode 3.0) y, por lo tanto, 4 bytes por "personaje" :) – SyntaxT3rr0r

+0

Gracias por la respuesta, eso es muy interesante, así que tal vez opte por el número de entradas. De hecho, la cadena generalmente tiene dos valores, cadenas realmente pequeñas de máximo 140 caracteres y cadenas muy grandes que representan un conjunto de valores, normalmente las cadenas pequeñas deberían ser más frecuentes. El costo para reconstruir la entrada es ejecutar un algoritmo de consenso y el ancho de banda, por lo que diría que no es proporcional al tamaño, pero que las entradas más grandes son aún más difíciles de reconstruir. Las grandes cadenas también están menos sujetas a ser accedidas. – Abbadon

+0

@Syntax - Buen punto - y aprendí algo cuando revisé los documentos antes de decirte que estabas equivocado :-) Siempre pensé que 'String.length()' devolvía el recuento de caracteres, y 'String.codePointCount() 'era necesario para convertir los caracteres complementarios en puntos de código que no sean BMP. Ahora sé que tengo más cuidado. – Anon