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/command
Files:
2 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        }
Note: See TracChangeset for help on using the changeset viewer.