Ticket #23085: 23085.patch

File 23085.patch, 8.7 KB (added by taylor.smock, 3 years ago)
  • src/org/openstreetmap/josm/data/conflict/ConflictCollection.java

    Subject: [PATCH] Fix #23085: Significantly reduce cost of selecting all primitives in a large dataset
    
    Direct CPU cycles were reduced by ~30% and memory allocations were reduced by ~70%.
    ---
    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/data/conflict/ConflictCollection.java b/src/org/openstreetmap/josm/data/conflict/ConflictCollection.java
    a b  
    173173     * @return true, if this collection includes a conflict for <code>my</code>; false, otherwise
    174174     */
    175175    public boolean hasConflictForMy(OsmPrimitive my) {
    176         return getConflictForMy(my) != null;
     176        return !conflicts.isEmpty() && getConflictForMy(my) != null;
    177177    }
    178178
    179179    /**
  • src/org/openstreetmap/josm/data/osm/DefaultNameFormatter.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/data/osm/DefaultNameFormatter.java b/src/org/openstreetmap/josm/data/osm/DefaultNameFormatter.java
    a b  
    2929import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
    3030import org.openstreetmap.josm.data.osm.history.HistoryRelation;
    3131import org.openstreetmap.josm.data.osm.history.HistoryWay;
     32import org.openstreetmap.josm.data.preferences.BooleanProperty;
     33import org.openstreetmap.josm.data.preferences.CachingProperty;
    3234import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
    3335import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetNameTemplateList;
    3436import org.openstreetmap.josm.spi.preferences.Config;
     
    4850    private static DefaultNameFormatter instance;
    4951
    5052    private static final List<NameFormatterHook> formatHooks = new LinkedList<>();
     53    private static final CachingProperty<Boolean> PROPERTY_SHOW_ID =
     54            new BooleanProperty("osm-primitives.showid", false).cached();
     55    private static final CachingProperty<Boolean> PROPERTY_SHOW_ID_NEW_PRIMITIVES =
     56            new BooleanProperty("osm-primitives.showid.new-primitives", false).cached();
     57    private static final CachingProperty<Boolean> PROPERTY_SHOW_VERSION =
     58            new BooleanProperty("osm-primitives.showversion", false).cached();
     59    private static final CachingProperty<Boolean> PROPERTY_SHOW_COOR =
     60            new BooleanProperty("osm-primitives.showcoor", false).cached();
     61    private static final CachingProperty<Boolean> PROPERTY_LOCALIZE_NAME =
     62            new BooleanProperty("osm-primitives.localize-name", true).cached();
    5163
    5264    private static final List<String> HIGHWAY_RAILWAY_WATERWAY_LANDUSE_BUILDING = Arrays.asList(
    5365            marktr("highway"), marktr("railway"), marktr("waterway"), marktr("landuse"), marktr("building"));
     
    142154     */
    143155    protected void decorateNameWithId(StringBuilder name, IPrimitive primitive) {
    144156        int version = primitive.getVersion();
    145         if (Config.getPref().getBoolean("osm-primitives.showid")) {
    146             long id = Config.getPref().getBoolean("osm-primitives.showid.new-primitives") ?
     157        if (Boolean.TRUE.equals(PROPERTY_SHOW_ID.get())) {
     158            long id = Boolean.TRUE.equals(PROPERTY_SHOW_ID_NEW_PRIMITIVES.get()) ?
    147159                    primitive.getUniqueId() : primitive.getId();
    148             if (Config.getPref().getBoolean("osm-primitives.showversion") && version > 0) {
     160            if (version > 0 && Boolean.TRUE.equals(PROPERTY_SHOW_VERSION.get())) {
    149161                name.append(tr(" [id: {0}, v{1}]", id, version));
    150162            } else {
    151163                name.append(tr(" [id: {0}]", id));
    152164            }
    153         } else if (Config.getPref().getBoolean("osm-primitives.showversion")) {
     165        } else if (Boolean.TRUE.equals(PROPERTY_SHOW_VERSION.get())) {
    154166            name.append(tr(" [v{0}]", version));
    155167        }
    156168    }
     
    187199            } else {
    188200                preset.nameTemplate.appendText(name, (TemplateEngineDataProvider) node);
    189201            }
    190             if (node.isLatLonKnown() && Config.getPref().getBoolean("osm-primitives.showcoor")) {
     202            if (node.isLatLonKnown() && Boolean.TRUE.equals(PROPERTY_SHOW_COOR.get())) {
    191203                name.append(" \u200E(");
    192204                name.append(CoordinateFormatManager.getDefaultFormat().toString(node, ", "));
    193205                name.append(")\u200C");
     
    196208        decorateNameWithId(name, node);
    197209
    198210        String result = name.toString();
    199         return formatHooks.stream().map(hook -> hook.checkFormat(node, result))
    200                 .filter(Objects::nonNull)
    201                 .findFirst().orElse(result);
    202 
     211        // This avoids memallocs from Stream map, filter and Optional creation.
     212        for (NameFormatterHook hook : formatHooks) {
     213            final String checkFormat = hook.checkFormat(node, result);
     214            if (checkFormat != null) {
     215                return checkFormat;
     216            }
     217        }
     218        return result;
    203219    }
    204220
    205221    private final Comparator<INode> nodeComparator = Comparator.comparing(this::format);
     
    274290    }
    275291
    276292    private static String formatLocalName(IPrimitive osm) {
    277         if (Config.getPref().getBoolean("osm-primitives.localize-name", true)) {
     293        if (Boolean.TRUE.equals(PROPERTY_LOCALIZE_NAME.get())) {
    278294            return osm.getLocalName();
    279295        } else {
    280296            return osm.getName();
     
    282298    }
    283299
    284300    private static String formatLocalName(HistoryOsmPrimitive osm) {
    285         if (Config.getPref().getBoolean("osm-primitives.localize-name", true)) {
     301        if (Boolean.TRUE.equals(PROPERTY_LOCALIZE_NAME.get())) {
    286302            return osm.getLocalName();
    287303        } else {
    288304            return osm.getName();
     
    529545     * @param primitive the primitive
    530546     */
    531547    protected void decorateNameWithId(StringBuilder name, HistoryOsmPrimitive primitive) {
    532         if (Config.getPref().getBoolean("osm-primitives.showid")) {
     548        if (Boolean.TRUE.equals(PROPERTY_SHOW_ID.get())) {
    533549            name.append(tr(" [id: {0}]", primitive.getId()));
    534550        }
    535551    }
  • src/org/openstreetmap/josm/data/osm/Way.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/data/osm/Way.java b/src/org/openstreetmap/josm/data/osm/Way.java
    a b  
    634634     * @since 13033
    635635     */
    636636    public boolean hasOnlyLocatableNodes() {
    637         return Arrays.stream(nodes).allMatch(Node::isLatLonKnown);
     637        // This is used in various places, some of which are on the UI thread.
     638        // If this is called many times, the memory allocations can become prohibitive, if
     639        // we use Java streams.
     640        // This can be easily tested by loading a large amount of ways into JOSM, and then
     641        // selecting everything.
     642        for (Node node : nodes) {
     643            if (!node.isLatLonKnown()) {
     644                return false;
     645            }
     646        }
     647        return true;
    638648    }
    639649
    640650    @Override
  • src/org/openstreetmap/josm/gui/PrimitiveRenderer.java

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/gui/PrimitiveRenderer.java b/src/org/openstreetmap/josm/gui/PrimitiveRenderer.java
    a b  
    4747    @Override
    4848    public Component getListCellRendererComponent(JList<? extends IPrimitive> list, IPrimitive value, int index,
    4949            boolean isSelected, boolean cellHasFocus) {
    50         Component def = defaultListCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
     50        // Use an empty string for the value to avoid expensive Object.toString calls, which will happen again in renderer.
     51        Component def = defaultListCellRenderer.getListCellRendererComponent(list, "", index, isSelected, cellHasFocus);
    5152        return renderer(def, value, list.getModel().getSize() > 1000);
    5253    }
    5354