Ignore:
Timestamp:
2020-03-23T14:24:59+01:00 (4 years ago)
Author:
GerdP
Message:

fix #18964: MapCSS rules using index are slow
Avoid a sequential search through all nodes when index matches first or last node only

Location:
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java

    r15990 r16199  
    448448        final String index;
    449449        final Op op;
     450        final boolean isFirstOrLast;
    450451
    451452        /**
     
    457458            this.index = index;
    458459            this.op = op;
     460            isFirstOrLast = op == Op.EQ && ("1".equals(index) || "-1".equals(index));
    459461        }
    460462
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

    r16191 r16199  
    3535import org.openstreetmap.josm.gui.mappaint.Environment;
    3636import org.openstreetmap.josm.gui.mappaint.Range;
     37import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.IndexCondition;
    3738import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.OpenEndPseudoClassCondition;
    3839import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    220221                    return;
    221222                }
    222                 for (int i = 0; i < count; i++) {
    223                     if (getter.apply(i).equals(e.osm) && link.matches(e.withParentAndIndexAndLinkContext(parent, i, count))) {
     223                // see #18964
     224                int step = firstAndLastOnly() ? count - 1 : 1;
     225                for (int i = 0; i < count; i += step) {
     226                    if (getter.apply(i).equals(e.osm)
     227                            && link.matches(e.withParentAndIndexAndLinkContext(parent, i, count))) {
    224228                        e.parent = parent;
    225229                        e.index = i;
     
    228232                    }
    229233                }
     234            }
     235
     236            private boolean firstAndLastOnly() {
     237                for (Condition c : link.conds) {
     238                    if (!(c instanceof IndexCondition) || !((IndexCondition) c).isFirstOrLast) {
     239                        return false;
     240                    }
     241                }
     242                return true;
    230243            }
    231244
Note: See TracChangeset for help on using the changeset viewer.