Changeset 8326 in josm


Ignore:
Timestamp:
2015-05-04T23:46:26+02:00 (6 years ago)
Author:
Don-vip
Message:

fix #11404 - High CPU load during tile loading in TMS layer and download box (patch by wiktorn)

Location:
trunk/src/org/openstreetmap/josm/data
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java

    r8318 r8326  
    2626import org.apache.commons.jcs.engine.behavior.ICacheElement;
    2727import org.openstreetmap.gui.jmapviewer.FeatureAdapter;
     28import org.openstreetmap.josm.Main;
    2829import org.openstreetmap.josm.data.cache.ICachedLoaderListener.LoadResult;
    2930import org.openstreetmap.josm.data.preferences.IntegerProperty;
     
    283284        } catch (Exception e) {
    284285            log.log(Level.WARNING, "JCS - Error while loading object from cache: {0}; {1}", new Object[]{e.getMessage(), getUrl()});
    285             log.log(Level.FINE, "Stacktrace", e);
     286            Main.warn(e);
    286287            for (ICachedLoaderListener l: listeners) {
    287288                l.loadingFinished(cacheData, LoadResult.FAILURE);
     
    382383            return handleNotFound();
    383384        } catch (Exception e) {
    384             log.log(Level.WARNING, "JCS - Exception during download " + getUrl(), e);
     385            log.log(Level.WARNING, "JCS - Exception during download {0}",  getUrl());
     386            Main.warn(e);
    385387        }
    386388        log.log(Level.WARNING, "JCS - Silent failure during download: {0}", getUrl());
  • trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java

    r8318 r8326  
    55import java.io.IOException;
    66import java.net.URL;
     7import java.util.HashSet;
    78import java.util.Map;
     9import java.util.Set;
    810import java.util.concurrent.ConcurrentHashMap;
     11import java.util.concurrent.ConcurrentMap;
    912import java.util.concurrent.Executor;
    1013import java.util.concurrent.Semaphore;
     
    3740    private static final Logger log = FeatureAdapter.getLogger(TMSCachedTileLoaderJob.class.getCanonicalName());
    3841    private Tile tile;
    39     private TileLoaderListener listener;
    4042    private volatile URL url;
     43
     44    // we need another deduplication of Tile Loader listeners, as for each submit, new TMSCachedTileLoaderJob was created
     45    // that way, we reduce calls to tileLoadingFinished, and general CPU load due to surplus Map repaints
     46    private static final ConcurrentMap<String,Set<TileLoaderListener>> inProgress = new ConcurrentHashMap<>();
    4147
    4248    /**
     
    133139        super(cache, connectTimeout, readTimeout, headers);
    134140        this.tile = tile;
    135         this.listener = listener;
     141        if (listener != null) {
     142            String deduplicationKey = getCacheKey();
     143            synchronized (inProgress) {
     144                Set<TileLoaderListener> newListeners = inProgress.get(deduplicationKey);
     145                if (newListeners == null) {
     146                    newListeners = new HashSet<>();
     147                    inProgress.put(deduplicationKey, newListeners);
     148                }
     149                newListeners.add(listener);
     150            }
     151        }
    136152    }
    137153
     
    227243    @Override
    228244    public void loadingFinished(CacheEntry object, LoadResult result) {
     245        Set<TileLoaderListener> listeners;
     246        synchronized (inProgress) {
     247            listeners = inProgress.remove(getCacheKey());
     248        }
     249
    229250        try {
    230             tile.finishLoading(); // whatever happened set that loading has finished
    231             switch(result){
    232             case FAILURE:
    233                 tile.setError("Problem loading tile");
    234                 // no break intentional here
    235             case SUCCESS:
    236                 handleNoTileAtZoom();
    237                 if (object != null) {
    238                     byte[] content = object.getContent();
    239                     if (content != null && content.length > 0) {
    240                         tile.loadImage(new ByteArrayInputStream(content));
     251            if(!tile.isLoaded()) { //if someone else already loaded tile, skip all the handling
     252                tile.finishLoading(); // whatever happened set that loading has finished
     253                switch(result){
     254                case FAILURE:
     255                    tile.setError("Problem loading tile");
     256                    // no break intentional here
     257                case SUCCESS:
     258                    handleNoTileAtZoom();
     259                    if (object != null) {
     260                        byte[] content = object.getContent();
     261                        if (content != null && content.length > 0) {
     262                            tile.loadImage(new ByteArrayInputStream(content));
     263                        }
    241264                    }
    242                 }
    243                 // no break intentional here
    244             case REJECTED:
    245                 // do nothing
    246             }
    247             if (listener != null) {
    248                 listener.tileLoadingFinished(tile, result.equals(LoadResult.SUCCESS));
     265                    // no break intentional here
     266                case REJECTED:
     267                    // do nothing
     268                }
     269            }
     270
     271            // always check, if there is some listener interested in fact, that tile has finished loading
     272            if (listeners != null) { // listeners might be null, if some other thread notified already about success
     273                for(TileLoaderListener l: listeners) {
     274                    l.tileLoadingFinished(tile, result.equals(LoadResult.SUCCESS));
     275                }
    249276            }
    250277        } catch (IOException e) {
     
    252279            tile.setError(e.getMessage());
    253280            tile.setLoaded(false);
    254             if (listener != null) {
    255                 listener.tileLoadingFinished(tile, false);
     281            if (listeners != null) { // listeners might be null, if some other thread notified already about success
     282                for(TileLoaderListener l: listeners) {
     283                    l.tileLoadingFinished(tile, false);
     284                }
    256285            }
    257286        }
Note: See TracChangeset for help on using the changeset viewer.