Looking for performance tuning ideas

The following code is a version of the usual function required in an analog watchface to rotate the various shapes (which all are polygons with four corners in my case). It works fine but is now one of two functions that take the most time. So I was wondering if it can be further tuned. I've tried with a lookup table for sin/cos - which doesn't make a difference - and with a 1-dimensional array for result - which is even slower - and now I'm out of ideas.

Does anyone see any way to further tune this code to make it faster?

    //! Rotate the four corner coordinates of a polygon used to draw a watch hand or a tick mark.
    //! 0 degrees is at the 12 o'clock position, and increases in the clockwise direction.
    //! @param shape Index of the shape
    //! @param angle Rotation angle in radians
    //! @return The rotated coordinates of the polygon (watch hand or tick mark)
    private function rotateCoords(shape as Shape, angle as Float) as Array< Array<Number> > {
        var sin = Math.sin(angle);
        var cos = Math.cos(angle);
        var shapeIdx = shape * 8;
        var result = new Array< Array<Number> >[4];
        for (var i = 0; i < 4; i++) {
            var idx = shapeIdx + i * 2;
            var x = (_coords[idx] * cos - _coords[idx + 1] * sin + 0.5).toNumber();
            var y = (_coords[idx] * sin + _coords[idx + 1] * cos + 0.5).toNumber();
            result[i] = [_screenCenter[0] + x, _screenCenter[1] + y];
        }
        return result;
    }

_coords is a long Array<Number> with the coordinates of all my shapes. The complete code is here.

  • I can only find a very simple explanation in the Monkey C reference guide: "Increment a numeric value by one, may be prefix or postfix", so yes, you may be right and this may not be intended to be used in assignments, like in Java or C++. But then its usefulness kind of reduces to giving you the familiar look and feel in for loops. Other than that, if these operators can only be used standalone, they are just two more shorthands for x+=1, which is already a shorthand for x=x+1.

    In my opinion, it really only makes sense to have these pre- and postincrement operators, if they work with an assignment, because then they actually do two different things.

    So maybe not a compiler bug, but feature request Slight smile

  • My example was to show that it is possible to easily rotate polygons if you work in a rotational coordinate system that basically mimics an analog watch. Like others here have said, you should only calculate what you need only as often as you need it. On my watch face you can see the sun rise and sun set polygons at their appropriate times near the bottom. Since I know when they are I don't have to recalculate the next one until the current one's time passes that day.

    This is not like a regular computer with vast resources that you don't need to be concerned with speed or memory efficiency. You will need to spend some time learning what works and doesn't in Monkey C, and incremental programming tricks that taken together will allow you to work within the execution time and memory limits.

  • After refactoring my code quite a bit once more, I now ended up with a single function to draw the second hand, essentially with all the other code that I previously had in other functions inlined. It seems function calls alone create a considerable overhead.

  • It seems everything in Monkey C has a fair amount of baggage. I don't know where the break is between how many times you need to do a certain thing and whether or not a function makes sense versus inlining. Mostly a case by case trial and error thing. You might split things out you only use once in a while just because it makes maintaining the overall code base easier, especially as you grow functionality.

  • If you've only been doing CIQ for a relatively short time, It might be hard to understand some things - there is a leaning curve, that's for sure.

    I saw your post in the 965 forum.  I've ported a bunch of my apps to the 265/965, and none of them took more that 5-10 minutes for example.  You may not know what to expect if you've only been doing this for an app or two.  A couple of my apps from 8 years back I've pretty much guttet and re-wrote once I has a better handle on things like fon difference, how the VM plays with the app, etc.

  • Something else is to use System.getTimer() to log the time in milliseconds certain blocks of code take to run. There can be big differences between what the sim profiler says and the real thing. There's a lot of overhead in System.println() so you'll need to account for that too.

  • In the sim, the resolution of getTimer() is only 16ms. so if you want to see much more accurate numbers, run it in a sideload. For watch faces that use onPartialUpdate, use watch face diagnostics in the sim.

  • Very true. If you are clever and have some memory to work with have the time tracing in onPartialUpdate add rows to a global array instead of using System.println() to get a better idea of the real time executing in a sideload. Dump the array after so many seconds after initialize(). On my Fenix 7x the sim averages 25ms, but the real device is closer to 6ms. The sim would crash with too much time where the real thing might not.

  • I've been using the watch face diagnostics tool in the sim to get an overall idea of how much time is spent in low power mode, and the profiler to identify the code that needs tuning. Previously I had it all nicely broken down into several functions each doing a part of the work needed in onPartialUpdate(), so profiling worked well. Now I've merged everything into a single function, so yes, I'll need to look into using some sort of stopwatches to measure parts of it in the future. Thanks for that input.

    Besides that, how do you measure the real-life overall performance of a watchface app, and maybe compare it with others? Is there any way (or an app) to measure the battery consumption of individual programs running on the watch perhaps?

  • Do you know of any watch face app, for which the code is available, that you'd say is a mature program, which has evolved over time like you describe you've evolved your own apps? I'd very much like to look at such code.