Changeset 17102 in josm for trunk


Ignore:
Timestamp:
2020-10-07T20:04:06+02:00 (4 years ago)
Author:
GerdP
Message:

fix #19881: Poor performance in delete action

  • avoids a repeated sequential search when the flag IS_OUTSIDE is already set. The search is sequential because in this scenario the collection in ignore is a SubclassFilteredCollection which always performs a sequential search when method contains() is used.
  • avoids to create change commands for ways which are in the collection of primitives which should be deleted
  • use Dataset.update() in DeleteCommand
Location:
trunk/src/org/openstreetmap/josm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/Command.java

    r16553 r17102  
    228228            if (osm.isIncomplete()) {
    229229                res |= IS_INCOMPLETE;
    230             } else if ((osm.isOutsideDownloadArea()
     230            } else if ((res & IS_OUTSIDE) == 0 && (osm.isOutsideDownloadArea()
    231231                    || (osm instanceof Node && !osm.isNew() && osm.getDataSet() != null && osm.getDataSet().getDataSourceBounds().isEmpty()))
    232232                            && (ignore == null || !ignore.contains(osm))) {
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r16573 r17102  
    185185    public boolean executeCommand() {
    186186        ensurePrimitivesAreInDataset();
    187         // Make copy and remove all references (to prevent inconsistent dataset (delete referenced) while command is executed)
    188         for (OsmPrimitive osm: toDelete) {
    189             if (osm.isDeleted())
    190                 throw new IllegalArgumentException(osm + " is already deleted");
    191             clonedPrimitives.put(osm, osm.save());
    192 
    193             if (osm instanceof Way) {
    194                 ((Way) osm).setNodes(null);
    195             } else if (osm instanceof Relation) {
    196                 ((Relation) osm).setMembers(null);
    197             }
    198         }
    199 
    200         for (OsmPrimitive osm: toDelete) {
    201             osm.setDeleted(true);
    202         }
    203 
     187
     188        getAffectedDataSet().update(() -> {
     189            // Make copy and remove all references (to prevent inconsistent dataset (delete referenced) while command is executed)
     190            for (OsmPrimitive osm : toDelete) {
     191                if (osm.isDeleted())
     192                    throw new IllegalArgumentException(osm + " is already deleted");
     193                clonedPrimitives.put(osm, osm.save());
     194
     195                if (osm instanceof Way) {
     196                    ((Way) osm).setNodes(null);
     197                } else if (osm instanceof Relation) {
     198                    ((Relation) osm).setMembers(null);
     199                }
     200            }
     201
     202            for (OsmPrimitive osm : toDelete) {
     203                osm.setDeleted(true);
     204            }
     205        });
    204206        return true;
    205207    }
     
    209211        ensurePrimitivesAreInDataset();
    210212
    211         for (OsmPrimitive osm: toDelete) {
    212             osm.setDeleted(false);
    213         }
    214 
    215         for (Entry<OsmPrimitive, PrimitiveData> entry: clonedPrimitives.entrySet()) {
    216             entry.getKey().load(entry.getValue());
    217         }
     213        getAffectedDataSet().update(() -> {
     214            for (OsmPrimitive osm : toDelete) {
     215                osm.setDeleted(false);
     216            }
     217
     218            for (Entry<OsmPrimitive, PrimitiveData> entry : clonedPrimitives.entrySet()) {
     219                entry.getKey().load(entry.getValue());
     220            }
     221        });
    218222    }
    219223
     
    427431        Set<Node> nodesToRemove = new HashSet<>(Utils.filteredCollection(primitivesToDelete, Node.class));
    428432        for (Way w : waysToBeChanged) {
    429             Way wnew = new Way(w);
    430             wnew.removeNodes(nodesToRemove);
    431             if (wnew.getNodesCount() < 2) {
     433            if (primitivesToDelete.contains(w))
     434                continue;
     435            List<Node> remainingNodes = w.calculateRemoveNodes(nodesToRemove);
     436            if (remainingNodes.size() < 2) {
    432437                primitivesToDelete.add(w);
    433438            } else {
    434                 cmds.add(new ChangeNodesCommand(w, wnew.getNodes()));
     439                cmds.add(new ChangeNodesCommand(w, remainingNodes));
    435440            }
    436441        }
  • trunk/src/org/openstreetmap/josm/data/osm/Way.java

    r16553 r17102  
    364364        boolean locked = writeLock();
    365365        try {
    366             boolean closed = isClosed() && selection.contains(lastNode());
    367             List<Node> copy = Arrays.stream(nodes)
    368                     .filter(n -> !selection.contains(n))
    369                     .collect(Collectors.toList());
    370 
    371             int i = copy.size();
    372             if (closed && i > 2) {
    373                 copy.add(copy.get(0));
    374             } else if (i >= 2 && i <= 3 && copy.get(0) == copy.get(i-1)) {
    375                 copy.remove(i-1);
    376             }
    377             setNodes(removeDouble(copy));
     366            setNodes(calculateRemoveNodes(selection));
    378367            for (Node n : selection) {
    379368                n.clearCachedStyle();
     
    382371            writeUnlock(locked);
    383372        }
     373    }
     374
     375    /**
     376     * Calculate the remaining nodes after a removal of the given set of {@link Node nodes} from this way.
     377     * @param selection The selection of nodes to remove. Ignored, if null
     378     * @return result of the removal, can be empty
     379     * @since 17101
     380     */
     381    public List<Node> calculateRemoveNodes(Set<? extends Node> selection) {
     382        if (selection == null || isIncomplete())
     383            return getNodes();
     384        boolean closed = isClosed() && selection.contains(lastNode());
     385        List<Node> copy = Arrays.stream(nodes)
     386                .filter(n -> !selection.contains(n))
     387                .collect(Collectors.toList());
     388
     389        int i = copy.size();
     390        if (closed && i > 2) {
     391            copy.add(copy.get(0));
     392        } else if (i >= 2 && i <= 3 && copy.get(0) == copy.get(i-1)) {
     393            copy.remove(i-1);
     394        }
     395        return removeDouble(copy);
    384396    }
    385397
Note: See TracChangeset for help on using the changeset viewer.