[josm-dev] Selection Performance

Dave Hansen dave at sr71.net
Thu Oct 8 08:47:02 BST 2009


On Thu, 2009-10-08 at 00:10 -0700, Dave Hansen wrote:
> It takes almost a second for me to do a mouse click and have a single
> object be selected.  I think it's worse for large data sets, but it
> seems to exist most of the time despite the size of the data set.
> Personally, I think a whole second to wait for a mouse click is pretty
> bad.
> 
> Most of the time appears to be spent notifying things about the
> selection change.  I just counted 110 of these, and we fire once for the
> clearSelection() and again for the new selection.  They all seem to add
> up to almost a second of latency.  I actually went and printed out a
> bunch of timestamps to confirm this.
> 
> Any thoughts on how to make this better?  I've been using my QuadBuckets
> code to make the click coordinate searches faster, but I'm clueless as
> to what to do with these notifiers.

Digging in a bit more... Virtually none of these actions care about the
contents of selections.  The vast majority just do:

    @Override
    protected void updateEnabledState() {
        setEnabled(getCurrentDataSet() != null && ! getCurrentDataSet().getSelected().isEmpty());
    }

The problem is that getSelected() iterates over the entire data set
looked for selected OsmPrimitives.  We do this ~112 times for each mouse
click.  That's a bit, um, suboptimal.

I tried a really quick and dirty solution which is to just keep a copy
of the selected primitives around.  That makes a *huge* difference.
Maybe we should have a heuristic where a selection that's less than 10%
(or whatever) of the size of the data set gets cached.  Any thoughts?

+    HashSet<OsmPrimitive> selectedPrimitives = new HashSet<OsmPrimitive>();
+
     public void setSelected(Collection<? extends OsmPrimitive> selection) {
-        clearSelection(nodes);
-        clearSelection(ways);
-        clearSelection(relations);
+        clearSelection(selectedPrimitives);
+        selectedPrimitives.clear();
         for (OsmPrimitive osm : selection) {
             osm.setSelected(true);
         }
+        selectedPrimitives.addAll(selection);
         fireSelectionChanged(selection);
     }
     public Collection<OsmPrimitive> getSelected() {
+        return selectedPrimitives;
     }

-- Dave





More information about the josm-dev mailing list