studio icon indicating copy to clipboard operation
studio copied to clipboard

UI_Init very slow

Open robkettridge opened this issue 1 year ago • 8 comments

Hello

We have a project in the works at the moment using EEZ-Studio with LVGL flow on an STM32 processor driving a small 2.5" screen. We have about 20 screens, 6 styles, 2 fonts, 5 small bitmaps. Nothing massively complicated. Just buttons and labels mostly.

The issue we are having is that executing UI_INIT takes about 11 seconds before the interface loads. We would really like to get this down considerably, or at least be able to show something on the screen whilst this is taking place. We're assuming that it's due to LVGL loading everything into RAM from ROM? Does it have to load every screen at start up? Is it possible to load screens on first use?

Are there any settings, or areas we should be looking at to speed this process up? We've done all the optimisations we can think of, and if anything it's getting slower.

Thanks

robkettridge avatar Dec 23 '24 13:12 robkettridge

It is true that currently EEZ Studio generates ui_init that will create all the screens in advance. I'm surprised it takes 11 seconds to create 20 screens. Fonts and bitmaps should be used from the ROM, so no preloading to RAM is required, I think.

Did you try to measure how much time it takes for each screen to be created? I think it would be interesting to do that. It can be done like this:

In ui.c modify ui_init:

void ui_init() {
    LV_LOG_USER("START");

    eez_flow_init(assets, sizeof(assets), (lv_obj_t **)&objects, sizeof(objects), images, sizeof(images), actions);

    LV_LOG_USER("END");
}

In screens.c modify create_screens:

void create_screens() {
    ui_create_groups();
    
    eez_flow_init_styles(add_style, remove_style);
    
    eez_flow_init_screen_names(screen_names, sizeof(screen_names) / sizeof(const char *));
    eez_flow_init_object_names(object_names, sizeof(object_names) / sizeof(const char *));
    eez_flow_init_group_names(group_names, sizeof(group_names) / sizeof(const char *));
    eez_flow_init_style_names(style_names, sizeof(style_names) / sizeof(const char *));
    
    lv_disp_t *dispp = lv_disp_get_default();
    lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), false, LV_FONT_DEFAULT);
    lv_disp_set_theme(dispp, theme);

    LV_LOG_USER("init");
    
    create_screen_main();

    LV_LOG_USER("main");

    create_screen_screen_a();
    
    LV_LOG_USER("a");
    
    create_screen_screen_b();

    LV_LOG_USER("b");

    create_screen_screen_c();

    LV_LOG_USER("c");
}

Printout example:

[User]	(0.093, +93)	 ui_init: START ui.c:187
[User]	(0.094, +1)	 create_screens: init screens.c:353
[User]	(0.099, +5)	 create_screens: main screens.c:357
[User]	(0.100, +1)	 create_screens: a screens.c:361
[User]	(0.101, +1)	 create_screens: b screens.c:365
[User]	(0.102, +1)	 create_screens: c screens.c:369
[User]	(0.103, +1)	 ui_init: END ui.c:191

So, in this case ui_init started at 0.093 sec and finished at 0.103 sec. So, 10 ms in total was required to initialize UI.

mvladic avatar Dec 23 '24 16:12 mvladic

I've just tried that but i'm not getting proper timestamps in the logs. I've got LV_LOG_USE_TIMESTAMP set to 1 in lv_conf.h Printout is showing this..

[00002229ms][INFO][main]: Before init [User] (0.000, +0) ui_init: START ui.c:2543 [User] (0.000, +0) create_screens: init screens.c:5024 [User] (0.000, +0) create_screens: 1 screens.c:5026 [User] (0.000, +0) create_screens: 2 screens.c:5028 [User] (0.000, +0) create_screens: 3 screens.c:5030 [User] (0.000, +0) create_screens: 4 screens.c:5032 [User] (0.000, +0) create_screens: 5 screens.c:5034 [User] (0.000, +0) create_screens: 6 screens.c:5036 [User] (0.000, +0) create_screens: 7 screens.c:5038 [User] (0.000, +0) create_screens: 8 screens.c:5040 [User] (0.000, +0) create_screens: 9 screens.c:5042 [User] (0.000, +0) create_screens: 10 screens.c:5044 [User] (0.000, +0) create_screens: 11 screens.c:5046 [User] (0.000, +0) create_screens: 12 screens.c:5048 [User] (0.000, +0) create_screens: 13 screens.c:5050 [User] (0.000, +0) create_screens: 14 screens.c:5052 [User] (0.000, +0) create_screens: 15 screens.c:5054 [User] (0.000, +0) create_screens: 16 screens.c:5056 [User] (0.000, +0) create_screens: 17 screens.c:5058 [User] (0.000, +0) create_screens: 18 screens.c:5060 [User] (0.000, +0) create_screens: 19 screens.c:5062 [User] (0.000, +0) ui_init: END ui.c:2545 [00011423ms][INFO][main]: After init

The [INFO] logs are our MBED trace logging.

I tried it with a simple printf statement per screen and they appeared to print relatively equally for each screen so it doesn't appear to be one particular screen taking ages to load.

robkettridge avatar Dec 30 '24 18:12 robkettridge

How long does it take for ui_init to execute?

Also, if I were you, I would still investigate why LV_LOG doesn't print the time.

mvladic avatar Dec 31 '24 09:12 mvladic

We had the ticker attach after the UI-Init which was why the times weren't showing. UI_INIT takes 9.2 seconds to complete

[00001204ms][INFO][main]: Before init
[User]  (0.000, +0)      ui_init: START ui.c:2543
[User]  (0.010, +10)     create_screens: init screens.c:5024
[User]  (0.515, +505)    create_screens: 1 screens.c:5026
[User]  (1.305, +790)    create_screens: 2 screens.c:5028
[User]  (1.530, +225)    create_screens: 3 screens.c:5030
[User]  (1.755, +225)    create_screens: 4 screens.c:5032
[User]  (1.940, +185)    create_screens: 5 screens.c:5034
[User]  (2.145, +205)    create_screens: 6 screens.c:5036
[User]  (2.275, +130)    create_screens: 7 screens.c:5038
[User]  (2.525, +250)    create_screens: 8 screens.c:5040
[User]  (3.940, +1415)   create_screens: 9 screens.c:5042
[User]  (4.170, +230)    create_screens: 10 screens.c:5044
[User]  (4.345, +175)    create_screens: 11 screens.c:5046
[User]  (4.530, +185)    create_screens: 12 screens.c:5048
[User]  (4.660, +130)    create_screens: 13 screens.c:5050
[User]  (4.745, +85)     create_screens: 14 screens.c:5052
[User]  (4.925, +180)    create_screens: 15 screens.c:5054
[User]  (5.100, +175)    create_screens: 16 screens.c:5056
[User]  (7.775, +2675)   create_screens: 17 screens.c:5058
[User]  (9.055, +1280)   create_screens: 18 screens.c:5060
[User]  (9.250, +195)    create_screens: 19 screens.c:5062
[User]  (9.255, +5)      ui_init: END ui.c:2545
[00010467ms][INFO][main]: After init

A common feature of the slowest screens (9, 17, &18) is that they all have roller widgets with many options (they're time selection rollers, so 24 options on the hours roller and 60 on the minutes roller), is there a more efficient way than just filling in the options box with all options with it set to Literal?

Thanks

robkettridge avatar Jan 06 '25 12:01 robkettridge

There's something very strange here, it's unbelievable that it's spending so much time on just initializing the screen.

Which STM32 processor do you have and at what frequency does it run?

mvladic avatar Jan 06 '25 18:01 mvladic

Good morning.

MCU is an STM32WB55RGV6 running at 32MHz.

robkettridge avatar Jan 07 '25 08:01 robkettridge

Trying to decide if the radio silence means 'Of course it won't run on that MCU' or that it should be fine :o/

robkettridge avatar Jan 16 '25 09:01 robkettridge

I have no experience with similar microcontroller. I only used STM32F4 and STM32F7 with the LVGL. Those microcontrollers work on much higher frequencies (180MHz and 216MHz). But, I still think that it shouldn't be that much slow. Function ui_init() doesn't do anything special, it just creates LVGL widgets. Are you using FreeRTOS or any other RTOS? Maybe there is some tesk executing parallel with GUI task that has higher priority. You can also continue to measure execution times deep down, maybe there is some function that is particularly slow.

mvladic avatar Jan 16 '25 09:01 mvladic