From 1e809d7915dc452fdb328642b3378751a1e814ce Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Tue, 13 Apr 2021 04:51:27 +0300 Subject: [PATCH] Add MapTileLayerSize for cache size --- .../plus/resources/AsyncLoadingThread.java | 67 ++++++++++--------- .../plus/resources/ResourceManager.java | 48 +++++++++++-- 2 files changed, 78 insertions(+), 37 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java b/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java index 8808b04e7b..16ee5b8a0b 100644 --- a/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java +++ b/OsmAnd/src/net/osmand/plus/resources/AsyncLoadingThread.java @@ -7,7 +7,7 @@ import net.osmand.data.RotatedTileBox; import net.osmand.map.ITileSource; import net.osmand.map.MapTileDownloader.DownloadRequest; import net.osmand.plus.SQLiteTileSource; -import net.osmand.plus.views.MapTileLayer; +import net.osmand.plus.resources.ResourceManager.MapTileLayerSize; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -16,19 +16,18 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Map.Entry; import java.util.Stack; /** * Thread to load map objects (POI, transport stops )async */ public class AsyncLoadingThread extends Thread { - - public static final int LIMIT_TRANSPORT = 200; - - private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class); - - Stack requests = new Stack(); + + private static final int CACHE_LAYER_SIZE_EXPIRE_TIME_MS = 30 * 1000; + + private static final Log log = PlatformUtil.getLog(AsyncLoadingThread.class); + + private final Stack requests = new Stack(); private final ResourceManager resourceManger; public AsyncLoadingThread(ResourceManager resourceManger) { @@ -65,7 +64,7 @@ public class AsyncLoadingThread extends Thread { updateBitmapTilesCache(); } } - if (tileLoaded || mapLoaded) { + if (tileLoaded || mapLoaded) { // use downloader callback resourceManger.getMapTileDownloader().fireLoadCallback(null); } @@ -78,21 +77,6 @@ public class AsyncLoadingThread extends Thread { } } - private void updateBitmapTilesCache() { - int maxCacheSize = 0; - for (Entry 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) { requests.push(req); } @@ -101,7 +85,6 @@ public class AsyncLoadingThread extends Thread { requests.push(req); } - public boolean isFilePendingToDownload(File fileToSave) { return resourceManger.getMapTileDownloader().isFilePendingToDownload(fileToSave); } @@ -114,6 +97,29 @@ public class AsyncLoadingThread extends Thread { 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 final String tileId; @@ -139,7 +145,7 @@ public class AsyncLoadingThread extends Thread { } public void saveTile(InputStream inputStream) throws IOException { - if(tileSource instanceof SQLiteTileSource){ + if (tileSource instanceof SQLiteTileSource) { ByteArrayOutputStream stream = null; try { stream = new ByteArrayOutputStream(inputStream.available()); @@ -149,14 +155,13 @@ public class AsyncLoadingThread extends Thread { try { ((SQLiteTileSource) tileSource).insertImage(xTile, yTile, zoom, stream.toByteArray()); } 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 { Algorithms.closeStream(inputStream); Algorithms.closeStream(stream); - } - } - else { + } + } else { super.saveTile(inputStream); } } @@ -224,6 +229,4 @@ public class AsyncLoadingThread extends Thread { this.mapLoadedListener = mapLoadedListener; } } - - } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index 31282e6232..fcbc76d5c4 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -100,7 +100,7 @@ public class ResourceManager { private List tilesCacheList = new ArrayList<>(); private BitmapTilesCache bitmapTilesCache; private GeometryTilesCache geometryTilesCache; - private Map mapTileLayerSizes = new ConcurrentHashMap<>(); + private List mapTileLayerSizes = new ArrayList<>(); private final OsmandApplication context; private List resourceListeners = new ArrayList<>(); @@ -121,7 +121,20 @@ public class ResourceManager { 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 { private BinaryMapIndexReader initialReader; private File filename; @@ -288,16 +301,41 @@ public class ResourceManager { resourceListeners.remove(listener); } - public Map getMapTileLayerSizes() { + public List getMapTileLayerSizes() { return mapTileLayerSizes; } 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 layerSizes = new ArrayList<>(mapTileLayerSizes); + layerSizes.add(new MapTileLayerSize(layer, tiles, System.currentTimeMillis())); + mapTileLayerSizes = layerSizes; + } } public void removeMapTileLayerSize(MapTileLayer layer) { - mapTileLayerSizes.remove(layer); + MapTileLayerSize layerSize = getMapTileLayerSize(layer); + if (layerSize != null) { + List 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() {