Is it possible to get average execution time each time onPartialUpdate() is called?

I'd like to be able to monitor the ebb and flow of the Average Execution time each time onPartialUpdate() is called.  I've tried using WatchUi.WatchFacePowerInfo.executionTimeAverage but that just returns null all of the time, even when WatchFaceDelegate shows the limit exceeded.  Am I doing something wrong or is it just not possible within onPartialUpdate() (or anywhere else)?

Top Replies

All Replies

  • The easiest thing is use "view watchface diagnostics" in the sim and just keep an eye on the times over a minute.

    The delegate in a WF only runs when you exceed the avg.

    Here's an example:

    class SLeanDelegate extends Ui.WatchFaceDelegate
    {
    	var view;
    	
    	function initialize(v) {
    		WatchFaceDelegate.initialize();
    		view=v;	
    	}
    	
        function onPowerBudgetExceeded(powerInfo) {
            Sys.println( "Average execution time: " + powerInfo.executionTimeAverage );
            Sys.println( "Allowed execution time: " + powerInfo.executionTimeLimit );
            view.do1hz=false;
        }
    }

    From the API guide:

    Power information provided when the power budget is exceeded during a call to onPartialUpdate().

    This is automatically passed to the onPowerBudgetExceeded() method when it is invoked.

  • Thanks, again, for the quick answer.  The WatchFaceDelegate only triggers when the average is exceeded.  What I was hoping to do was to monitor the rolling average over the full minute to see where the big hits were occurring.  I know that it is possible to monitor those values by looking at the Watchface Diagnostics but they change rather too rapidly for my old eyes!  I guess what I could do is to record a minute's worth of the diagnostics and then play it back more slowly but that is a bit tedious to say the least. - Oh well.

  • One of the things I suggested back when this was introduced was that in WF Diagnostics, there be a graph showing each call in  the current minute.

    With a basic analog WF doing 1hz, what you'd see is a sine wave, with the low values at 3 and 9 and the high values at 12 and 6.  This is why an average is used because things change during the minute.

  • I've tried using WatchUi.WatchFacePowerInfo.executionTimeAverage but that just returns null all of the time

    That makes sense because the only place you can get a WatchFacePowerInfo that has been initialized is in WatchFaceDelegate::onPowerBudgetExceeded().

    If you just want to know how long the partial update took you could do something like this...

    function onPartialUpdate(dc) {
        var startTime = System.getTimer();
        
        do_onPartialUpdate(dc);
        
        var elaspedMilliseconds = System.getTimer() - startTime;
        // do something with it
    }

    Unfortunately, I'm not sure that you're going to find that very useful.

    The power budget system uses a heuristic to estimate the execution time values. We run some performance benchmarks on devices and determine the "cost" for various draw operations and execution of virtual machine code. We estimate the total cost of the call to onPartialUpdate by summing the estimated costs of each operation during the minute, and then report an average.

    This means that the numbers you will get from an actual wall clock time are likely to be very different from the execution time that we've estimated.

    We do this because the resolution of the timer is not great and we need to be able to get reasonable estimates for relative cost of operations that are much smaller than the timer resolution.

  • Thanks for that info.  How practical would it be to provide that info either as a call to powerinfo or as an added field in the sim diagnostics?  I appreciate that there is a level of complexity in the behind-the-scenes calculations but it seems to me that if it could be made available it would be very helpful in pinpointing the times and therefore the processing that is causing the greatest power drain.  In the meantime I can at least use your suggestion - thanks.

  • I'm not sure it will help.  I put Travis code in one of my WFs (well kind of)

        function onPartialUpdate(dc) {         
        	if(!do1hz) {return;}
    var startTime = System.getTimer();    
        	if(MySettings.showSecs) {
    	    	var clockTime = System.getClockTime();
        		doSecs(dc,clockTime.sec,true);
        	}
        	doHr(dc,true);
    System.println(""+(System.getTimer()-startTime));    	
        }

    The println is the current clock minus the startTime, and in the sim, its's pretty consistently 0, with an occasional 16.

    Watchface Diagnostics is in the 9-10ms range with this WF

  • The println is the current clock minus the startTime, and in the sim, its's pretty consistently 0, with an occasional 16.

    This is expected. The resolution of the timer used on a windows system is something like 15ms. You may see better results on a physical device, I honestly do not know.

    How practical would it be to provide that info either as a call to powerinfo or as an added field in the sim diagnostics?

    I'm not sure I see the need for a new API here. It seems that the proper place for this is in the development tools.

    A new API is going to allow a watch face to make decisions at runtime to avoid exceeding the budget, which seems great. But if the solution is to not update something less frequently, then maybe the simpler solution is just do that all the time.

  • Ah, that explains why I was seeing a majority of 0s!  Thanks for clearing that up.  As it happens, though, Jim's code is more useful than it might appear.  In my case I was seeing mostly 0 with small clusters of 15 or 16 milliseconds - which were presumably therefore identifying hotspots in the code.  It does seem, though, that the elapsed time reported by this method is less than half that reported by diagnostics.

  • It does seem, though, that the elapsed time reported by this method is less than half that reported by diagnostics.

    Right. As I mentioned previously, the diagnostics system doesn't actually measure execution time. Instead it measures an estimated cost metric that should be approximately proportional to the execution time.

    Additionally, when running the simulator you're comparing the execution time of the code running on a PC class CPU against the cost metric for that same code running on a virtualized device with a wristwatch class CPU.