732 views
in GUI Development by

Hi

I have a performance related question.
In our touch screen test, the user slides a finger across the display and red dots are drawn to follow the trace. However we see a gap after the first dot is drawn. It works fine subsequently.

We are finding the first Update() (in the main loop) takes a long time to complete after entering the screen, of the order 300 - 400ms. Subseqeunt Update() completes in ~20ms. What I mean by 'after entering the screen' is from a previous menu this test screen is entered, UpdateLayout() and Update() are already called to show the test screen (white background with grid), and the screen is waiting for touch action. This long Update() in question happens after the user touches the screen. Since a red dot consists of two small rectangles only, we would have thought it can be completed reasonably quickly.
Is there any way this can be optimised?

We are using a STM32F7 running at 200Mhz.

Thanks and regards
Steven

1 Answer

0 votes
by

Hello Steven,

without knowing your project, it is difficult to indicate the cause of the delay. Generally, the Update() function will perform the same steps every time it is invoked. This means, if your GUI consists of e.g. 10 graphical objects, the invocation of Update() will process these objects in the similar manner with every invocation. Thus, the initial delay is difficult to explain.

One question: in your project do you have eventually overriden the method Draw()? We have noticed that many developers love to override the Draw() method in their own GUI components and implement there some buisiness logic which in fact has nothing to do with the real screen update (even: draw). This may slow down or even disturb the screen composition. Can you check it?

Generally regarding delays: If you show a new GUI component (you enter a new screen), we expect some initial delay before the component appears. Entering a new screen means that you create a new instance of the corresponding GUI component. During this creation time the component is initialized. If the component uses bitmaps, fonts or strings, the affected resources are loaded now. The impact of this loading phase depends on the number, size and format of the used resources. For example, bitmaps stored in compressed format need to be decompressed before they can be used. So it is resonable that sometimes it takes time for the first presentation of a GUI component.

However, according to your explanation this does not apply to your problem. As you write, the test component is already visible ...

Another question to avoid misunderstanding: do you observe the performance issue in the target system or in the Prototyping environment?

My suggestion would be to simplify the application and test the performance behavior. For example, you could reduce the application to consist of the test screen only and then anylaze the performance.

Another suggestion, if you have the professional license (provided with source code) you can recompile the Graphics Engine and the Runtime Environment with activated profiling (with defined C macro EW_PRINT_PERF_COUNTERS). In this case all internal operations are measured and collected. With the function EwPrintPerfCounters() you can print the collected information. You see e.g. how often function CopyBitmap(), etc. has been called and how much time it took. So it is possible to detect bottlenecks. With the function EwResetPerfCounters() you reset the collected information for a new measure cycle.

Best regards

Paul Banach

by

Hi Paul

At last I am able to get back to this issue after a long break.
One clarification to make: the long delay is seen on the target system only and not on the Prototyping environment.
By the Draw() method do you mean the various XXX_Draw() methods in generated codes? The generated codes is not modified.

To use EwPrintPerfCounter() and since EwGetPerfCounter() is not implemented, I added codes to EwGetPerfCounter() similar to this:
  unsigned long eticks = getElaspedTimeTicks();
  *aSeconds         = (eticks/ticks_per_second));
  *aMicroSeconds    = *aSeconds * 1000000;
  *aCPUMicroseconds = eticks;

Do these look right to you?

With that the perfcounter metrics for a normal Update() (not the first one) is:

-----------------------------------------------------------------------------------------------
Group Name                    [ Calls ]  [  Time  Total  ]
-----------------------------------------------------------------------------------------------
Total Time                            1   16.000 ms   0.1% of real CPU time
Graphics_Engine_API                  36   13.000 ms  81.3%
Platform_Integration_API             26   12.000 ms  75.0%
-----------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------
Graphics_Engine_API           [ Calls ]  [  Time  Total  ]  [Time Avg]  [Time Min]  [Time Max]
-----------------------------------------------------------------------------------------------
EwBeginUpdate                         1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwEndUpdate                           1   12.000 ms  75.0%   12.000 ms   12.000 ms   12.000 ms
EwFillRectangle                       7    1.000 ms   6.3%    0.142 ms    0.000 ms    1.000 ms
EwCopyBitmap                          8    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwTileBitmap                         12    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwDrawLine                            1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwDrawText                            3    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwDrawBitmapFrame                     3    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
-----------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------
Platform_Integration_API      [ Calls ]  [  Time  Total  ]  [Time Avg]  [Time Min]  [Time Max]
-----------------------------------------------------------------------------------------------
EwGfxBeginUpdate                      1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxEndUpdate                        1   10.000 ms  62.5%   10.000 ms   10.000 ms   10.000 ms
EwGfxLockSurface                      1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxUnlockSurface                    1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxDrawLine                         1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxFill                             9    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxCopy                            12    2.000 ms  12.5%    0.166 ms    0.000 ms    1.000 ms
-----------------------------------------------------------------------------------------------

And the perfcounter metrics for the first Update() is:

-----------------------------------------------------------------------------------------------
Group Name                    [ Calls ]  [  Time  Total  ]
-----------------------------------------------------------------------------------------------
Total Time                            1  211.000 ms   0.1% of real CPU time
Graphics_Engine_API                  89  207.000 ms  98.1%
Platform_Integration_API            822  178.000 ms  84.4%
-----------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------
Graphics_Engine_API           [ Calls ]  [  Time  Total  ]  [Time Avg]  [Time Min]  [Time Max]
-----------------------------------------------------------------------------------------------
EwBeginUpdate                         1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwEndUpdate                           1  202.000 ms  95.7%  202.000 ms  202.000 ms  202.000 ms
EwFillRectangle                       8    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwCopyBitmap                         16    1.000 ms   0.5%    0.062 ms    0.000 ms    1.000 ms
EwTileBitmap                         24    1.000 ms   0.5%    0.041 ms    0.000 ms    1.000 ms
EwDrawLine                           24    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwDrawText                            9    2.000 ms   0.9%    0.222 ms    0.000 ms    1.000 ms
EwDrawBitmapFrame                     6    1.000 ms   0.5%    0.166 ms    0.000 ms    1.000 ms
-----------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------
Platform_Integration_API      [ Calls ]  [  Time  Total  ]  [Time Avg]  [Time Min]  [Time Max]
-----------------------------------------------------------------------------------------------
EwGfxBeginUpdate                      1    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxEndUpdate                        1    6.000 ms   2.8%    6.000 ms    6.000 ms    6.000 ms
EwGfxLockSurface                      4   58.000 ms  27.5%   14.500 ms    0.000 ms   58.000 ms
EwGfxUnlockSurface                    4    0.000 ms   0.0%    0.000 ms    0.000 ms    0.000 ms
EwGfxDrawLine                        24   43.000 ms  20.4%    1.791 ms    0.000 ms    3.000 ms
EwGfxFill                            33    8.000 ms   3.8%    0.242 ms    0.000 ms    4.000 ms
EwGfxCopy                           755   63.000 ms  29.9%    0.083 ms    0.000 ms    2.000 ms
-----------------------------------------------------------------------------------------------

One last point. I was able to 'hide' this issue by starting a timer when the screen is entered. After 50ms the timer calls a slot method to draw an invisible dot on the screen. The timer is then disabled. The idea is to start the first Update() as soon as possible after entering the screen.
With that there is no noticeable delay after the first dot drawn.

Can you see anything from the above and the perfcounter results?

Thanks and regards
Steven

 

by
Hello Steven,

thank you for providing the performance measurement results. Very interesting!

Based on these results there are two points that should be analyzed / solved:

1. As you can see, within the first update, there is not only the red dot drawn, there are additionally 24 line draw operations (I assume the grid), 16 bitmap copy and 24 bitmap tile operations. At the end, this results in 755 copy operations. Without knowing your implementation of the UI component, it is difficult to detect the reason. Maybe there are several Wallpapers or Bitmap Frames in the background?

2. Within the first update the function call EwGfxLockSurface() takes 58ms. This function is just waiting for the completion of a previous drawing operation - or to be more precise it is waiting for the interrupt of the DMA2D. However, there is no drawing operation that will take 58ms. This leads to a couple of questions: Are you using an operating system? Are you using interrupts with higher priority than DMA2D interrupt and which are taking a long time? Are you disabling interrupts temporarily?

I assume that there is some other activity in the system which results in a temporary blocking of the display update...

If possible, can you reduce the problem to an example that you can share?

Best regards

Manfred.

Embedded Wizard Website | Privacy Policy | Imprint

...