glastonbridge / ScanVox

Vocal machine-listening music making machine.
GNU General Public License v3.0
11 stars 0 forks source link

gui optimisation: don't invalidate entire screen? #45

Open danstowell opened 13 years ago

danstowell commented 13 years ago

Using TraceView I checked what was taking the CPU time in ScanVox. The SCAudio stuff took about 50%, which is to be expected; next heaviest was a lot of android.view traversal and repainting.

Arranger.listenToMessages() invalidates the whole view whenever a clock tick comes in. It could be made more efficient by only invalidating the Rect in which the old+new clock-cursor lie. However, this could only be done (I think) by refactoring the GUI so that there wasn't one single view, so not sure how easy this is.

An alternative might be to cache the rendered bitmap (i.e. of the whole view with blobs on) so that under a 'normal' clock tick we just paste the whole bitmap in and put the clock cursor on top. (Would need to invalidate that cache on reorient, record, drag, etc)

glastonbridge commented 13 years ago

I think I've made this one worse by splitting the GUI into three layered views. Before my commit yesterday[1] there was one real view, and it was calling onDraw recursively. It is since then that I've started seeing the buffer overflows on the streak. The reason for this change was because I wanted to use the pre-rolled ListView widget, and this way made it easier and clearer to do. My intuition[2] is that it is android's own housekeeping of views (laying out, invalidation resolution etc), rather than their onDraw methods which are taking the time, in which case we should go back to a single-view system with its own measure/layout/draw routines. This may require experimentation, I'll have a play this week.

[1] http://github.com/glastonbridge/ScanVox/commit/6beea273b21068ba1f4edfb27832a994da8d4b39 [2] not worth the paper it's printed on

danstowell commented 13 years ago

I think you're right about the housekeeping - after noting this issue I read [3] which basically treats the GUI-widget-tree-size as the thing to optimise.

Today I changed the code (not committed it, nor updated to your recent refactor) so Arranger holds its own Canvas+Bitmap, then in onDraw() it simply writes the cached Bitmap out and then superimposes the clock-cursor. The CPU difference was smaller than I'd hoped - when there are two blobs onscreen the CPU usage is very similar to the simpler version (the c.drawBitmap() call then takes much of the CPU time) but it should at least scale better (i.e. improves efficiency when there are many blobs onscreen).

It's kinda disappointing how much of the CPU time something as simple as drawGrid() takes...

Another overkill alternative would be to do the graphics in an openGL Canvas, which potentially moves much of the graphics to the GPU and therefore further away from harming the audio!

[3] http://developer.android.com/resources/articles/layout-tricks-efficiency.html