Changeset 31466 in osm


Ignore:
Timestamp:
2015-08-08T12:30:05+02:00 (9 years ago)
Author:
wiktorn
Message:

Performance improvements.

  • MemoryTileCache now can be initialized with desired cache size
  • Tile.loadPlaceholderFromCache now uses lazy evaluation and created BufferedImage only when something is found in cache. This dramatically improves MapView drawing when a lot of tiles is missing
Location:
applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java

    r31434 r31466  
    2323     * Default cache size
    2424     */
    25     protected int cacheSize = 200;
     25    protected int cacheSize;
    2626
    2727    protected final Map<String, CacheEntry> hash;
     
    3636     */
    3737    public MemoryTileCache() {
     38        this(200);
     39    }
     40
     41    /**
     42     * Constructs a new {@code MemoryTileCache}.
     43     * @param cacheSize size of the cache
     44     */
     45    public MemoryTileCache(int cacheSize) {
     46        this.cacheSize = cacheSize;
    3847        hash = new HashMap<>(cacheSize);
    3948        lruTiles = new CacheLinkedListElement();
    4049    }
     50
    4151
    4252    @Override
  • applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java

    r31439 r31466  
    1010import java.util.HashMap;
    1111import java.util.Map;
     12import java.util.concurrent.Callable;
    1213
    1314import javax.imageio.ImageIO;
     
    8788    }
    8889
     90    private static class CachedCallable<V> implements Callable<V> {
     91        private V result = null;
     92        private Callable<V> callable;
     93
     94        /**
     95         * Wraps callable so it is evaluated only once
     96         * @param callable to cache
     97         */
     98        public CachedCallable(Callable<V> callable) {
     99            this.callable = callable;
     100        }
     101
     102        @Override
     103        public synchronized V call() {
     104            try {
     105                if (result == null) {
     106                    result = callable.call();
     107                }
     108                return result;
     109            } catch (Exception e) {
     110                // this should not happen here
     111                throw new RuntimeException(e);
     112            }
     113        }
     114    }
     115
    89116    /**
    90117     * Tries to get tiles of a lower or higher zoom level (one or two level
     
    93120     */
    94121    public void loadPlaceholderFromCache(TileCache cache) {
    95         BufferedImage tmpImage = new BufferedImage(source.getTileSize(), source.getTileSize(), BufferedImage.TYPE_INT_RGB);
    96         Graphics2D g = (Graphics2D) tmpImage.getGraphics();
     122        /*
     123         *  use LazyTask as creation of BufferedImage is very expensive
     124         *  this way we can avoid object creation until we're sure it's needed
     125         */
     126        final CachedCallable<BufferedImage> tmpImage = new CachedCallable<>(new Callable<BufferedImage>() {
     127            @Override
     128            public BufferedImage call() throws Exception {
     129                return new BufferedImage(source.getTileSize(), source.getTileSize(), BufferedImage.TYPE_INT_RGB);
     130            }
     131        });
     132
    97133        for (int zoomDiff = 1; zoomDiff < 5; zoomDiff++) {
    98134            // first we check if there are already the 2^x tiles
     
    103139                int xtileHigh = xtile << zoomDiff;
    104140                int ytileHigh = ytile << zoomDiff;
    105                 double scale = 1.0 / factor;
    106                 g.setTransform(AffineTransform.getScaleInstance(scale, scale));
     141                final double scale = 1.0 / factor;
     142
     143                /*
     144                 * use LazyTask for graphics to avoid evaluation of tmpImage, until we have
     145                 * something to draw
     146                 */
     147                CachedCallable<Graphics2D> graphics = new CachedCallable<>(new Callable<Graphics2D>() {
     148                    @Override
     149                    public Graphics2D call() throws Exception {
     150                        Graphics2D g = (Graphics2D) tmpImage.call().getGraphics();
     151                        g.setTransform(AffineTransform.getScaleInstance(scale, scale));
     152                        return g;
     153                    }
     154                });
     155
    107156                int paintedTileCount = 0;
    108157                for (int x = 0; x < factor; x++) {
     
    111160                        if (tile != null && tile.isLoaded()) {
    112161                            paintedTileCount++;
    113                             tile.paint(g, x * source.getTileSize(), y * source.getTileSize());
     162                            tile.paint(graphics.call(), x * source.getTileSize(), y * source.getTileSize());
    114163                        }
    115164                    }
    116165                }
    117166                if (paintedTileCount == factor * factor) {
    118                     image = tmpImage;
     167                    image = tmpImage.call();
    119168                    return;
    120169                }
     
    125174                int xtileLow = xtile >> zoomDiff;
    126175                int ytileLow = ytile >> zoomDiff;
    127                 int factor = 1 << zoomDiff;
    128                 double scale = factor;
    129                 AffineTransform at = new AffineTransform();
    130                 int translateX = (xtile % factor) * source.getTileSize();
    131                 int translateY = (ytile % factor) * source.getTileSize();
    132                 at.setTransform(scale, 0, 0, scale, -translateX, -translateY);
    133                 g.setTransform(at);
     176                final int factor = 1 << zoomDiff;
     177                final double scale = factor;
     178                CachedCallable<Graphics2D> graphics = new CachedCallable<>(new Callable<Graphics2D>() {
     179                    @Override
     180                    public Graphics2D call() throws Exception {
     181                        Graphics2D g = (Graphics2D) tmpImage.call().getGraphics();
     182                        AffineTransform at = new AffineTransform();
     183                        int translateX = (xtile % factor) * source.getTileSize();
     184                        int translateY = (ytile % factor) * source.getTileSize();
     185                        at.setTransform(scale, 0, 0, scale, -translateX, -translateY);
     186                        g.setTransform(at);
     187                        return g;
     188                    }
     189
     190                });
     191
    134192                Tile tile = cache.getTile(source, xtileLow, ytileLow, zoomLow);
    135193                if (tile != null && tile.isLoaded()) {
    136                     tile.paint(g, 0, 0);
    137                     image = tmpImage;
     194                    tile.paint(graphics.call(), 0, 0);
     195                    image = tmpImage.call();
    138196                    return;
    139197                }
Note: See TracChangeset for help on using the changeset viewer.