Mal rendimiento con Guava Cache en Android

Utilizamos una carga de Google Guava LoadingCache para mapas de bits en una aplicación de Android. En la aplicación estoy ejecutando un hilo de dibujo, que pinta los mapas de bits en el caché a un lienzo. Si un mapa de bits específico no está en la memoria caché, no se dibuja de modo que ninguna carga bloqueará el hilo de dibujo.

Sin embargo, los resultados de la pintura en la tartamudez visual y los fotogramas por segundo tasa no es como nos gustaría. Lo clavo hasta el método getIfPresent() de la caché. Eso solo toma más del 20% de las aplicaciones de tiempo total de la CPU. En getIfPresent() LocalCache$Segment.get() toma más del 80% del tiempo:

Profiling-guava-cache.jpg

Tenga en cuenta, esto es sólo una búsqueda de un mapa de bits ya presente. Nunca ocurrirá una carga en get() . Pensé que habría una sobrecarga de contabilidad en get() para la cola LRU que decide qué desalojo tiene lugar si el segmento está lleno. Pero esto es por lo menos un orden de magnitud más lento de lo que un Key-Lookup en LRU-LinkedHashmap.get() me daría.

Utilizamos una caché para obtener búsquedas rápidas si un elemento está en la caché, si la búsqueda es lenta, no tiene sentido colocarla en caché. También intenté getAllPresent(a) y asMap() pero da igual rendimiento.

La versión de la biblioteca es: guava-11.0.1.jar

LoadingCache se define de la siguiente manera:

 LoadingCache<TileKey, Bitmap> tiles = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<TileKey,Bitmap>() { @Override public Bitmap load(TileKey tileKey) { System.out.println("Loading in " + Thread.currentThread().getName() + " " + tileKey.x + "-" + tileKey.y); final File[][] tileFiles = surfaceState.mapFile.getBuilding() .getFloors().get(tileKey.floorid) .getBackground(tileKey.zoomid).getTileFiles(); String tilePath = tileFiles[tileKey.y][tileKey.x].getAbsolutePath(); Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; return BitmapFactory.decodeFile(tilePath, options); } }); 

Mis preguntas son:

  • ¿Lo uso mal?
  • ¿Es imposible su implementación para Android?
  • ¿He extrañado una opción de configuración?
  • ¿Se trata de un problema conocido con el caché en el que se está trabajando?

Actualizar:

Después de unos 100 cuadros pintados los CacheStats son:

 I/System.out( 6989): CacheStats{hitCount=11992, missCount=97, loadSuccessCount=77, loadExceptionCount=0, totalLoadTime=1402984624, evictionCount=0} 

Después de que missCount permanece básicamente igual que los incrementos hitCount. En este caso, la caché es lo suficientemente grande como para que las cargas ocurran escasamente, pero getIfPresent es lento, no obstante.

CacheBuilder fue diseñado para el almacenamiento en caché del lado del servidor, donde la concurrencia era una preocupación principal. Por lo tanto, se negocia fuera de línea única y la memoria a cambio de un mejor comportamiento multi-threaded. Los desarrolladores de Android deben usar LruCache , LinkedHashMap o similares donde el rendimiento y la memoria de un único subproceso son las principales preocupaciones. En el futuro puede haber un concurrencyLevel = 0 para indicar que se requiere una caché ligera y no concurrente.

El código de Android no siempre se optimiza de la misma manera que en una JVM. Lo que puede funcionar muy bien en Java podría no funcionar tan bien en Android. Te sugiero que escribas una caché muy simple. Por ejemplo, usando LinkedHashMap.removeEldestEntry () y ver cómo va.

  • Mi parse StartTime y EndTime no se conectan correctamente con mi aplicación. ¿Ayuda? (Java)
  • Uso de? Android: attr / in aplicaciones compatibles hacia atrás
  • ¿Está Android N Stream API backported a versiones inferiores?
  • Archivo de Android a Base64 utilizando streaming a veces se pierde 2 bytes
  • ¿Cómo obtener los datos de Firebase Push Notification y mostrarlos en tu actividad de Android?
  • Java: Acceso a recursos y la ley de Demeter
  • ¿Cómo puedo depurar el consumo de memoria RAM de mi aplicación Android en tiempo de ejecución?
  • La aplicación android no libera Bluetooth correctamente al salir
  • Java.lang.SecurityException: inválido nombre del paquete: com.google.android.gms
  • Abra la cámara nativa de Android con OpenCV
  • ¿Podemos añadir texto a un dibujable?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.