Changeset 7056 in josm for trunk/src


Ignore:
Timestamp:
2014-05-03T11:32:22+02:00 (11 years ago)
Author:
bastiK
Message:

mapcss: optimization by converting very hot double loop into single loop (gain ~ 20%)

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r7055 r7056  
    123123            final TagCheck check = new TagCheck(rule);
    124124            boolean containsSetClassExpression = false;
    125             for (Instruction i : rule.declaration) {
     125            for (Instruction i : rule.declaration.instructions) {
    126126                if (i instanceof Instruction.AssignmentInstruction) {
    127127                    final Instruction.AssignmentInstruction ai = (Instruction.AssignmentInstruction) i;
     
    161161            }
    162162            if (check.errors.isEmpty() && !containsSetClassExpression) {
    163                 throw new RuntimeException("No throwError/throwWarning/throwOther given! You should specify a validation error message for " + rule.selectors);
     163                throw new RuntimeException("No throwError/throwWarning/throwOther given! You should specify a validation error message for " + rule.selector);
    164164            } else if (check.errors.size() > 1) {
    165                 throw new RuntimeException("More than one throwError/throwWarning/throwOther given! You should specify a single validation error message for " + rule.selectors);
     165                throw new RuntimeException("More than one throwError/throwWarning/throwOther given! You should specify a single validation error message for " + rule.selector);
    166166            }
    167167            return check;
     
    191191            for (Iterator<MapCSSRule> it = source.rules.iterator(); it.hasNext(); ) {
    192192                MapCSSRule x = it.next();
    193                 if (x.selectors.size() == 1) {
    194                     Selector sel = x.selectors.get(0);
    195                     if (sel instanceof GeneralSelector) {
    196                         GeneralSelector gs = (GeneralSelector) sel;
    197                         if ("meta".equals(gs.base) && gs.getConditions().isEmpty()) {
    198                             it.remove();
    199                         }
     193                if (x.selector instanceof GeneralSelector) {
     194                    GeneralSelector gs = (GeneralSelector) x.selector;
     195                    if ("meta".equals(gs.base) && gs.getConditions().isEmpty()) {
     196                        it.remove();
    200197                    }
    201198                }
     
    214211
    215212        Selector whichSelectorMatchesEnvironment(Environment env) {
    216             for (Selector i : rule.selectors) {
    217                 env.clearSelectorMatchingInformation();
    218                 if (i.matches(env)) {
    219                     return i;
    220                 }
     213            env.clearSelectorMatchingInformation();
     214            if (rule.selector.matches(env)) {
     215                return rule.selector;
    221216            }
    222217            return null;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj

    r6970 r7056  
    1818import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
    1919import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
     20import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule.Declaration;
    2021import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
    2122import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
     
    469470void sheet(MapCSSStyleSource sheet):
    470471{
    471     MapCSSRule r;
    472472}
    473473{
     
    476476    (
    477477        try {
    478             r=rule() { if (r != null) { sheet.rules.add(r); } } w()
     478            rule() w()
    479479        } catch (MapCSSException mex) {
    480480            error_skipto(RBRACE, mex);
     
    488488}
    489489
    490 MapCSSRule rule():
     490void rule():
    491491{
    492492    List<Selector> selectors = new ArrayList<Selector>();
    493493    Selector sel;
    494     List<Instruction> decl;
     494    Declaration decl;
    495495}
    496496{
     
    501501    )*
    502502    decl=declaration()
    503     { return new MapCSSRule(selectors, decl); }
     503    {
     504        for (Selector s : selectors) {
     505            sheet.rules.add(new MapCSSRule(s, decl));
     506        }
     507    }
    504508}
    505509
     
    707711}
    708712
    709 List<Instruction> declaration() :
     713Declaration declaration() :
    710714{
    711715    List<Instruction> ins = new ArrayList<Instruction>();
     
    723727            ( <EQUAL> val=expression() )?
    724728            { ins.add(new Instruction.AssignmentInstruction(key.image, val == null ? true : val, true)); }
    725             ( <RBRACE> { return ins; } | <SEMICOLON> w() )
     729            ( <RBRACE> { return new Declaration(ins); } | <SEMICOLON> w() )
    726730        )
    727731    |
     
    732736                { ins.add(new Instruction.AssignmentInstruction(key.image, val, false)); }
    733737                w()
    734                 ( <RBRACE> { return ins; } | <SEMICOLON> w() )
     738                ( <RBRACE> { return new Declaration(ins); } | <SEMICOLON> w() )
    735739            |
    736740            LOOKAHEAD( expression() ( <SEMICOLON> | <RBRACE> ) )
    737741                val=expression()
    738742                { ins.add(new Instruction.AssignmentInstruction(key.image, val, false)); }
    739                 ( <RBRACE> { return ins; } | <SEMICOLON> w() )
     743                ( <RBRACE> { return new Declaration(ins); } | <SEMICOLON> w() )
    740744            |
    741745                val=readRaw() w() { ins.add(new Instruction.AssignmentInstruction(key.image, val, false)); }
     
    743747    )*
    744748    <RBRACE>
    745     { return ins; }
     749    { return new Declaration(ins); }
    746750}
    747751
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java

    r6070 r7056  
    99public class MapCSSRule {
    1010
    11     public List<Selector> selectors;
    12     public List<Instruction> declaration;
     11    public Selector selector;
     12    public Declaration declaration;
    1313
    14     public MapCSSRule(List<Selector> selectors, List<Instruction> declaration) {
    15         this.selectors = selectors;
     14    public static class Declaration {
     15        public List<Instruction> instructions;
     16        // usedId is an optimized way to make sure that
     17        // each declaration is only applied once for each primitive,
     18        // even if multiple of the comma separated selectors in the
     19        // rule match.
     20        public int usedId;
     21
     22        public Declaration(List<Instruction> instructions) {
     23            this.instructions = instructions;
     24            usedId = 0;
     25        }
     26    }
     27   
     28    public MapCSSRule(Selector selector, Declaration declaration) {
     29        this.selector = selector;
    1630        this.declaration = declaration;
    1731    }
     
    2337     */
    2438    public void execute(Environment env) {
    25         for (Instruction i : declaration) {
     39        for (Instruction i : declaration.instructions) {
    2640            i.execute(env);
    2741        }
     
    3044    @Override
    3145    public String toString() {
    32         return Utils.join(",", selectors) + " {\n  " + Utils.join("\n  ", declaration) + "\n}";
     46        return selector + " {\n  " + Utils.join("\n  ", declaration.instructions) + "\n}";
    3347    }
    3448}
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r7054 r7056  
    5858    private ZipFile zipFile;
    5959
     60    private static int usedId = 1;
     61   
    6062    public MapCSSStyleSource(String url, String name, String shortdescription) {
    6163        super(url, name, shortdescription);
     
    118120        // optimization: filter rules for different primitive types
    119121        for (MapCSSRule r: rules) {
    120             List<Selector> nodeSel = new ArrayList<>();
    121             List<Selector> waySel = new ArrayList<>();
    122             List<Selector> relationSel = new ArrayList<>();
    123             List<Selector> multipolygonSel = new ArrayList<>();
    124             for (Selector sel : r.selectors) {
    125                 // find the rightmost selector, this must be a GeneralSelector
    126                 Selector selRightmost = sel;
    127                 while (selRightmost instanceof ChildOrParentSelector) {
    128                     selRightmost = ((ChildOrParentSelector) selRightmost).right;
    129                 }
    130                 Selector optimizedSel = sel.optimizedBaseCheck();
    131                 switch (((GeneralSelector) selRightmost).getBase()) {
    132                     case "node":
    133                         nodeSel.add(optimizedSel);
    134                         break;
    135                     case "way":
    136                         waySel.add(optimizedSel);
    137                         break;
    138                     case "area":
    139                         waySel.add(optimizedSel);
    140                         multipolygonSel.add(optimizedSel);
    141                         break;
    142                     case "relation":
    143                         relationSel.add(optimizedSel);
    144                         multipolygonSel.add(optimizedSel);
    145                         break;
    146                     case "*":
    147                         nodeSel.add(optimizedSel);
    148                         waySel.add(optimizedSel);
    149                         relationSel.add(optimizedSel);
    150                         multipolygonSel.add(optimizedSel);
    151                         break;
    152                 }
    153             }
    154             nodeRules.add(new MapCSSRule(nodeSel, r.declaration));
    155             wayRules.add(new MapCSSRule(waySel, r.declaration));
    156             relationRules.add(new MapCSSRule(relationSel, r.declaration));
    157             multipolygonRules.add(new MapCSSRule(multipolygonSel, r.declaration));
     122            // find the rightmost selector, this must be a GeneralSelector
     123            Selector selRightmost = r.selector;
     124            while (selRightmost instanceof ChildOrParentSelector) {
     125                selRightmost = ((ChildOrParentSelector) selRightmost).right;
     126            }
     127            MapCSSRule optRule = new MapCSSRule(r.selector.optimizedBaseCheck(), r.declaration);
     128            switch (((GeneralSelector) selRightmost).getBase()) {
     129                case "node":
     130                    nodeRules.add(optRule);
     131                    break;
     132                case "way":
     133                    wayRules.add(optRule);
     134                    break;
     135                case "area":
     136                    wayRules.add(optRule);
     137                    multipolygonRules.add(optRule);
     138                    break;
     139                case "relation":
     140                    relationRules.add(optRule);
     141                    multipolygonRules.add(optRule);
     142                    break;
     143                case "*":
     144                    nodeRules.add(optRule);
     145                    wayRules.add(optRule);
     146                    relationRules.add(optRule);
     147                    multipolygonRules.add(optRule);
     148                    break;
     149            }
    158150        }
    159151        rules.clear();
     
    219211        NEXT_RULE:
    220212        for (MapCSSRule r : rules) {
    221             for (Selector s : r.selectors) {
    222                 if ((s instanceof GeneralSelector)) {
    223                     GeneralSelector gs = (GeneralSelector) s;
    224                     if (gs.getBase().equals(type)) {
    225                         if (!gs.matchesConditions(env)) {
    226                             continue NEXT_RULE;
    227                         }
    228                         r.execute(env);
     213            if ((r.selector instanceof GeneralSelector)) {
     214                GeneralSelector gs = (GeneralSelector) r.selector;
     215                if (gs.getBase().equals(type)) {
     216                    if (!gs.matchesConditions(env)) {
     217                        continue NEXT_RULE;
    229218                    }
     219                    r.execute(env);
    230220                }
    231221            }
     
    254244            }
    255245        }
     246        usedId++;
    256247        RULE: for (MapCSSRule r : matchingRules) {
    257             for (Selector s : r.selectors) {
    258                 env.clearSelectorMatchingInformation();
    259                 if (s.matches(env)) { // as side effect env.parent will be set (if s is a child selector)
    260                     if (s.getRange().contains(scale)) {
    261                         mc.range = Range.cut(mc.range, s.getRange());
    262                     } else {
    263                         mc.range = mc.range.reduceAround(scale, s.getRange());
    264                         continue;
     248            env.clearSelectorMatchingInformation();
     249            if (r.selector.matches(env)) { // as side effect env.parent will be set (if s is a child selector)
     250                Selector s = r.selector;
     251                if (s.getRange().contains(scale)) {
     252                    mc.range = Range.cut(mc.range, s.getRange());
     253                } else {
     254                    mc.range = mc.range.reduceAround(scale, s.getRange());
     255                    continue;
     256                }
     257
     258                if (r.declaration.usedId == usedId) continue; // don't apply a declaration block more than once
     259                r.declaration.usedId = usedId;
     260                String sub = s.getSubpart();
     261                if (sub == null) {
     262                    sub = "default";
     263                }
     264                else if ("*".equals(sub)) {
     265                    for (Entry<String, Cascade> entry : mc.getLayers()) {
     266                        env.layer = entry.getKey();
     267                        if (Utils.equal(env.layer, "*")) {
     268                            continue;
     269                        }
     270                        r.execute(env);
    265271                    }
    266 
    267                     String sub = s.getSubpart();
    268                     if (sub == null) {
    269                         sub = "default";
    270                     }
    271                     else if ("*".equals(sub)) {
    272                         for (Entry<String, Cascade> entry : mc.getLayers()) {
    273                             env.layer = entry.getKey();
    274                             if (Utils.equal(env.layer, "*")) {
    275                                 continue;
    276                             }
    277                             r.execute(env);
    278                         }
    279                     }
    280                     env.layer = sub;
    281                     r.execute(env);
    282                     continue RULE;
    283272                }
     273                env.layer = sub;
     274                r.execute(env);
     275                continue RULE;
    284276            }
    285277        }
Note: See TracChangeset for help on using the changeset viewer.