How to measure FPS and CPU Usage on Azure RTOS GUIX with STM32H750B-Disco board

S.A.M 56 Reputation points
2021-07-01T07:14:59.127+00:00

Hello,

After this question that I asked few weeks ago, now my GUI is ready, but I need to measure how good its performance is on my board, eg. FPS, CPU usage and stuffs like that;
I searched in the GUIX documentation but didn't found anything related to FPS or performance measurement,
would be appreciated if anybody helps how to do so, does GUIX has performance measurement itself? Or I need to integrate it manually myself?

Thanks in advance,
Best regards.

Azure RTOS
Azure RTOS
An Azure embedded development suite including a small but powerful operating system for resource-constrained devices.
332 questions
0 comments No comments
{count} votes

8 answers

Sort by: Most helpful
  1. Ken Maxwell 706 Reputation points Microsoft Employee
    2021-07-08T13:16:06.383+00:00

    drawing_initiate() and drawing_complete() become nested based on how many levels of parent/child widgets are being updated. GUIX keeps track of the nesting level via canvas->gx_canvas_draw_nesting. drawing_inititate() calls the display driver gx_display_driver_drawing_initiate function only on the first entry, and call the display driver gx_display_driver_drawing_complete only on the last exit from these nested functions. So if you put your counter in the display driver callback functions you will get an accurate frame count.

    Best Regards,

    Ken

    2 people found this answer helpful.
    0 comments No comments

  2. Ken Maxwell 706 Reputation points Microsoft Employee
    2021-07-12T14:40:42.033+00:00

    I don't really like adding this to gxe_system_canvas_refresh(), because this function is only invoked if the application manually initiates a canvas refresh operation. Typically the canvas refresh operation is not invoked manually, it is invoked internally by GUIX when the GUIX event queue is emptied. When GUIX internally invokes the canvas refresh, it does not go through the error-checking "_gxe" wrapper.

    I would like to dive into why the display_driver_drawing_complete isn't giving you accurate results. As you can see this is invoked only when the canvas drawing operation "unwinds" and we are done with a drawing sequence, as the code snippet in canvas_drawing_complete below:

    if (canvas -> gx_canvas_draw_nesting > 0)
    {
        if (display -> gx_display_driver_drawing_complete)
        {
            display -> gx_display_driver_drawing_complete(display, canvas);
        }
    

    If you are getting here multiple times for each drawing sequence, it sounds like you are manually invoking the canvas refresh and you are doing this for each dirty widget, rather than combining all the updates into one canvas refresh? That could slow things down considerably, because we also toggle frame buffers when a canvas refresh sequence is complete. So in your example, if you update three dials individually, that would trigger three frame bugger toggle operations. Better to wrap all three updates into one sequence. So like this in pseudo-code:

    gx_canvas_drawing_initiate()    // mark the beginning
    
         for each dial:
              gx_canvas_drawing_initiate()
              dial->gx_widget_draw()
              gx_canvas_drawing_complete()
    
    gx_canvas_drawing_complete()   // the end, buffer toggle and FPS count
    

    This happens for you automatically if you just mark the widgets dirty and let GUIX do the canvas refresh internally. If you are manually invoking canvas refresh, then you have control over how this happens. I would generally advise just to mark the widgets dirty and let GUIX take care of redrawing what needs to be redrawn, but you could have very good reasons for doing things as you are, every application is different.

    Hope this helps,

    Ken

    2 people found this answer helpful.
    0 comments No comments

  3. Ken Maxwell 706 Reputation points Microsoft Employee
    2021-07-12T14:43:22.267+00:00

    The code formatting didn't come out correct above, I want to be sure you understand the nesting so let me give it another try:

    gx_canvas_drawing_initiate()
    
           for each dial:
                  gx_canvas_drawing_initiate()
                  dial->gx_widget_draw()
                  gx_canvas_drawing_complete()
    
    gx_canvas_drawing_complete()
    
    
         
    
    2 people found this answer helpful.
    0 comments No comments

  4. QuantumCache 20,271 Reputation points
    2021-07-02T18:47:57.1+00:00

    Hello @S.A.M , below is the response from the product team, I hope this helps with your initial query.

    Execution profile can be used in this case. Please refer to : threadx/tx_execution_profile.h at master · azure-rtos/threadx (github.com)
    Between the CPU busy/idle information and the detailed drawing timing information, hopefully this gives you everything you need.

    If the response is helpful, please click "Accept Answer" and upvote it and leave your feedback.

    For any further help in this matter please comment in the below section.

    1 person found this answer helpful.

  5. Ken Maxwell 706 Reputation points Microsoft Employee
    2021-07-07T14:35:41.18+00:00

    To calculate FPS you really need to key in more on the display driver buffer toggle (equivalent to canvas refresh). I don't know what you are using exactly for display driver, but I believe you are using STM32 display driver? All display drivers can provide callback functions that are invoked at the start and conclusion of each GUIX canvas refresh. For the ST display driver developed in-house, we provide gx_chromeart_drawing_initiate and gx_chromeart_drawing_complete callback functions. These are enabled via a #define (GX_TIMING _ENABLE). The default operation of these callback functions is to toggle a GPIO pin, but you could of course change this to do whatever you like. So it is pretty simple to put a logic analyzer on this GPIO pin to measure the frame rate. If you don't want to go to that trouble you could simply increment a counter and use another timer to measure a 1-second interval.

    Keep in mind that the GUIX canvas refresh is driven by the application, not hardware such as an LCD vertical refresh interrupt. So the application really determines, within the performance limits of the target, how often a canvas refresh occurs. If nothing is changing on the display, the refresh rate is 0 FPS. If something is changing based on pen-drag input, the refresh rate will be determined by the touch input driver event generation interval. If you have configured animations, the refresh rate will be determined by the animation timer interval. Again, this assumes the drawing can "keep up" with the animation timer. The upper limit of FPS will be determined by a lot of factors: Display area being updated, color depth, complexity of drawing operations (alpha blending, RLE encoding, etc..) and total available CPU/memory bandwidth.

    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.