Add MapTileLayerSize for cache size

This commit is contained in:
Vitaliy 2021-04-13 04:51:27 +03:00
parent a0e52f355f
commit 1e809d7915
2 changed files with 78 additions and 37 deletions

View file

@ -7,7 +7,7 @@ import net.osmand.data.RotatedTileBox;
import net.osmand.map.ITileSource; import net.osmand.map.ITileSource;
import net.osmand.map.MapTileDownloader.DownloadRequest; import net.osmand.map.MapTileDownloader.DownloadRequest;
import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.views.MapTileLayer; import net.osmand.plus.resources.ResourceManager.MapTileLayerSize;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -16,19 +16,18 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map.Entry;
import java.util.Stack; import java.util.Stack;
/** /**
* Thread to load map objects (POI, transport stops )async * Thread to load map objects (POI, transport stops )async
*/ */
public class AsyncLoadingThread extends Thread { public class AsyncLoadingThread extends Thread {
public static final int LIMIT_TRANSPORT = 200; private static final int CACHE_LAYER_SIZE_EXPIRE_TIME_MS = 30 * 1000;
private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class); private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class);
Stack<Object> requests = new Stack<Object>(); private final Stack<Object> requests = new Stack<Object>();
private final ResourceManager resourceManger; private final ResourceManager resourceManger;
public AsyncLoadingThread(ResourceManager resourceManger) { public AsyncLoadingThread(ResourceManager resourceManger) {
@ -65,7 +64,7 @@ public class AsyncLoadingThread extends Thread {
updateBitmapTilesCache(); updateBitmapTilesCache();
} }
} }
if (tileLoaded || mapLoaded) { if (tileLoaded || mapLoaded) {
// use downloader callback // use downloader callback
resourceManger.getMapTileDownloader().fireLoadCallback(null); resourceManger.getMapTileDownloader().fireLoadCallback(null);
} }
@ -78,21 +77,6 @@ public class AsyncLoadingThread extends Thread {
} }
} }
private void updateBitmapTilesCache() {
int maxCacheSize = 0;
for (Entry<MapTileLayer, Integer> entry : resourceManger.getMapTileLayerSizes().entrySet()) {
MapTileLayer layer = entry.getKey();
if (layer.isVisible()) {
maxCacheSize += entry.getValue();
}
}
BitmapTilesCache bitmapTilesCache = resourceManger.getBitmapTilesCache();
if (maxCacheSize > 0 && maxCacheSize * 1.2 < bitmapTilesCache.getMaxCacheSize()) {
log.info("Bitmap tiles to load in memory : " + maxCacheSize);
bitmapTilesCache.setMaxCacheSize(maxCacheSize);
}
}
public void requestToLoadTile(TileLoadDownloadRequest req) { public void requestToLoadTile(TileLoadDownloadRequest req) {
requests.push(req); requests.push(req);
} }
@ -101,7 +85,6 @@ public class AsyncLoadingThread extends Thread {
requests.push(req); requests.push(req);
} }
public boolean isFilePendingToDownload(File fileToSave) { public boolean isFilePendingToDownload(File fileToSave) {
return resourceManger.getMapTileDownloader().isFilePendingToDownload(fileToSave); return resourceManger.getMapTileDownloader().isFilePendingToDownload(fileToSave);
} }
@ -114,6 +97,29 @@ public class AsyncLoadingThread extends Thread {
resourceManger.getMapTileDownloader().requestToDownload(req); resourceManger.getMapTileDownloader().requestToDownload(req);
} }
private void updateBitmapTilesCache() {
int maxCacheSize = 0;
long currentTime = System.currentTimeMillis();
for (MapTileLayerSize layerSize : resourceManger.getMapTileLayerSizes()) {
if (layerSize.markToGCTimestamp != null && currentTime - layerSize.markToGCTimestamp > CACHE_LAYER_SIZE_EXPIRE_TIME_MS) {
resourceManger.removeMapTileLayerSize(layerSize.layer);
} else if (currentTime - layerSize.activeTimestamp > CACHE_LAYER_SIZE_EXPIRE_TIME_MS) {
layerSize.markToGCTimestamp = currentTime + CACHE_LAYER_SIZE_EXPIRE_TIME_MS;
} else if (layerSize.markToGCTimestamp == null) {
maxCacheSize += layerSize.tiles;
}
}
BitmapTilesCache bitmapTilesCache = resourceManger.getBitmapTilesCache();
int oldCacheSize = bitmapTilesCache.getMaxCacheSize();
if (maxCacheSize != 0 && maxCacheSize * 1.2 < oldCacheSize || maxCacheSize > oldCacheSize) {
if (maxCacheSize / 2.5 > oldCacheSize) {
bitmapTilesCache.clearTiles();
}
log.info("Bitmap tiles to load in memory : " + maxCacheSize);
bitmapTilesCache.setMaxCacheSize(maxCacheSize);
}
}
public static class TileLoadDownloadRequest extends DownloadRequest { public static class TileLoadDownloadRequest extends DownloadRequest {
public final String tileId; public final String tileId;
@ -139,7 +145,7 @@ public class AsyncLoadingThread extends Thread {
} }
public void saveTile(InputStream inputStream) throws IOException { public void saveTile(InputStream inputStream) throws IOException {
if(tileSource instanceof SQLiteTileSource){ if (tileSource instanceof SQLiteTileSource) {
ByteArrayOutputStream stream = null; ByteArrayOutputStream stream = null;
try { try {
stream = new ByteArrayOutputStream(inputStream.available()); stream = new ByteArrayOutputStream(inputStream.available());
@ -149,14 +155,13 @@ public class AsyncLoadingThread extends Thread {
try { try {
((SQLiteTileSource) tileSource).insertImage(xTile, yTile, zoom, stream.toByteArray()); ((SQLiteTileSource) tileSource).insertImage(xTile, yTile, zoom, stream.toByteArray());
} catch (IOException e) { } catch (IOException e) {
log.warn("Tile x="+xTile +" y="+ yTile+" z="+ zoom+" couldn't be read", e); //$NON-NLS-1$//$NON-NLS-2$ log.warn("Tile x=" + xTile + " y=" + yTile + " z=" + zoom + " couldn't be read", e); //$NON-NLS-1$//$NON-NLS-2$
} }
} finally { } finally {
Algorithms.closeStream(inputStream); Algorithms.closeStream(inputStream);
Algorithms.closeStream(stream); Algorithms.closeStream(stream);
} }
} } else {
else {
super.saveTile(inputStream); super.saveTile(inputStream);
} }
} }
@ -224,6 +229,4 @@ public class AsyncLoadingThread extends Thread {
this.mapLoadedListener = mapLoadedListener; this.mapLoadedListener = mapLoadedListener;
} }
} }
} }

View file

@ -100,7 +100,7 @@ public class ResourceManager {
private List<TilesCache> tilesCacheList = new ArrayList<>(); private List<TilesCache> tilesCacheList = new ArrayList<>();
private BitmapTilesCache bitmapTilesCache; private BitmapTilesCache bitmapTilesCache;
private GeometryTilesCache geometryTilesCache; private GeometryTilesCache geometryTilesCache;
private Map<MapTileLayer, Integer> mapTileLayerSizes = new ConcurrentHashMap<>(); private List<MapTileLayerSize> mapTileLayerSizes = new ArrayList<>();
private final OsmandApplication context; private final OsmandApplication context;
private List<ResourceListener> resourceListeners = new ArrayList<>(); private List<ResourceListener> resourceListeners = new ArrayList<>();
@ -121,7 +121,20 @@ public class ResourceManager {
ROUTING, ROUTING,
TRANSPORT_ROUTING TRANSPORT_ROUTING
} }
public static class MapTileLayerSize {
final MapTileLayer layer;
Long markToGCTimestamp = null;
long activeTimestamp;
int tiles;
public MapTileLayerSize(MapTileLayer layer, int tiles, long activeTimestamp) {
this.layer = layer;
this.tiles = tiles;
this.activeTimestamp = activeTimestamp;
}
}
public static class BinaryMapReaderResource { public static class BinaryMapReaderResource {
private BinaryMapIndexReader initialReader; private BinaryMapIndexReader initialReader;
private File filename; private File filename;
@ -288,16 +301,41 @@ public class ResourceManager {
resourceListeners.remove(listener); resourceListeners.remove(listener);
} }
public Map<MapTileLayer, Integer> getMapTileLayerSizes() { public List<MapTileLayerSize> getMapTileLayerSizes() {
return mapTileLayerSizes; return mapTileLayerSizes;
} }
public void setMapTileLayerSizes(MapTileLayer layer, int tiles) { public void setMapTileLayerSizes(MapTileLayer layer, int tiles) {
mapTileLayerSizes.put(layer, tiles); MapTileLayerSize layerSize = getMapTileLayerSize(layer);
if (layerSize != null) {
if (layerSize.markToGCTimestamp != null) {
layerSize.markToGCTimestamp = null;
layerSize.activeTimestamp = System.currentTimeMillis();
}
layerSize.tiles = tiles;
} else {
List<MapTileLayerSize> layerSizes = new ArrayList<>(mapTileLayerSizes);
layerSizes.add(new MapTileLayerSize(layer, tiles, System.currentTimeMillis()));
mapTileLayerSizes = layerSizes;
}
} }
public void removeMapTileLayerSize(MapTileLayer layer) { public void removeMapTileLayerSize(MapTileLayer layer) {
mapTileLayerSizes.remove(layer); MapTileLayerSize layerSize = getMapTileLayerSize(layer);
if (layerSize != null) {
List<MapTileLayerSize> layerSizes = new ArrayList<>(mapTileLayerSizes);
layerSizes.remove(layerSize);
mapTileLayerSizes = layerSizes;
}
}
private MapTileLayerSize getMapTileLayerSize(MapTileLayer layer) {
for (MapTileLayerSize layerSize : mapTileLayerSizes) {
if (layerSize.layer == layer) {
return layerSize;
}
}
return null;
} }
public void resetStoreDirectory() { public void resetStoreDirectory() {