Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[stem-dev] Some performance enhancement ideas for Map View

Hi Chris,

Per our discussion on the STEM call today, here are a few ideas for 
further performance improvements on the Map View / Graph Map View.  I have 
done a rough implementation of each just to gauge performance / 
feasibility, but they're not fully implemented.

1.  Move Drawing off UI Thread

A SWT Graphics Context (GC) can draw to an image in regular threads. 
Currently we do all the drawing on the UI thread, which 1) has to wait 
until it's available to draw and 2) locks the UI while drawing, which can 
make the UI seem unresponsive for large periods during simulations.

In my example, created a new Eclipse Job that executes the draw routine 
and creates two images:  the filled polygons and borders (See #2).  This 
job is scheduled by the simulationChanged(...) listener and runs 
asynchronously.  When it finishes, the two images are stored in memory.

The paintControl() method, which draws the UI and runs on the UI thread, 
simply draws the two images directly onto the Control.  The total cost of 
a repaint is ~30ms - that is the time the UI is bound, vs. 300-2000 ms 

Upside:  The combined image is cached, allowing less drawing directly onto 
the UI, thus a faster and more responsive UI.  Refresh job is easier 
managed using Jobs framework (vs. asyncExec(...))
Downside:  The image is further asynchronous from the simulation; 
complicates panning and zooming.

2.  Cache the Polygon Borders Image

50% of the draw time for each Map refresh is drawing the polygon borders. 
For a fixed map perspective (pan/zoom settings), the borders and thus the 
image do not change from step to step, and can be drawn onto a cached 
image and reused. Also, you can apply the alpha (which we like) uniformly 
at the bitmap level, vs having to calculate the alpha redundantly. The 
cost of drawing the image is about 10ms vs. 400-700ms for rendering the 
polygons.  When the map perspective changes, the polygons must be redrawn. 
(* panning with no clipping is an exception)

Upside:  2x average speed-up; can retain border transparency at trivial 
Downside:  Increased memory usage; complicates panning and zooming

3.  Cache the Filled Polygons Image; define a value differential to force 

This is kind of tricky, but it also useful.  Step-by-step, the vast 
majority of the nodes do not change in value appreciably (that is, enough 
to trigger a change in relative value index in the map view).  By 
extension, for a fixed map perspective, most of the filled polygons do not 
need to be refreshed for each redraw (in fact, most are probably white). 

With your alpha pre-calculations, we can now overdraw cached images, 
retaining the "look" of alpha, but without worrying about additive 
blending of the previous pixel values and we don't have to pay the 2x cost 
to redraw the background then draw the fill.

The idea is to set a (configurable) differential in relative value before 
the polygon is redrawn.  On our index of 0-255, this could be something 
like a change of 5% in relative value (10-15 indexed values of alpha) 
would be required before an individual region / polygon is redrawn.  With 
map perspective changes, the whole thing must be redrawn. (* panning with 
no clipping is an exception)

Upside:  Up to another 2x speed-up
Downside:  Increased memory usage; complicates panning and zooming; lots 
of edge cases to take care of; lose accuracy & resolution in the map.

4.  Make sure clipping is working


A quick and dirty implementation of 1-3 in the current MapCanvas shows a 
decrease in average draw time from 700ms to 80ms per redraw (range of 10ms 
to 1200ms) for the USAMexico scenario with a 5% relative value difference 
before redraw.  Now, there will be steps when it's going to be much 
higher, but for the most part, it's much faster.

Now, one issue is this gets us further and further away from having a 
"correct" map view --- but that leads to the last part.  With an average 
update of 80ms, a simulation-synchronous map view is no longer that big of 
a burden (especially if it's not binding the UI).  And the redraw 
differential would be configurable, so you can get a completely accurate, 
synchronous map with two configuration switches.  A synchronous draw will 
also be faster, as it's not going to be competing with the simulation for 
CPU time.

The biggest downside to all this is panning and zooming will have to be 
addressed, as all of these options make it even less interactive than it 
is now (which isn't saying much ...).

I'm interested in hearing everyone's thoughts.  I'm also happy to help 
implement any of these changes.


Back to the top