Seeing much slower style refresh performance on v7 vs v6

I just finished migrating my v6 GUI to v7. My UI uses a lot of elements that change color via a style refresh.

Measuring the style refresh:

  • using v6, updating 17 styles takes 5,721 microseconds
  • using v7, updating 13 styles takes about 144,074 microseconds

This is running on an IMXRT1052, with a 320x240 display, using a full screen sized buffer for LVGL

This makes v7 practically unusable in my situation. I see some other topics mentioning worse performance on v7, but I wasn’t expecting this much of a difference. Is this expected?

v7 style updates are going to be slower than v6. However, on such a fast processor, it should not be running that slowly.

So no, I wouldn’t expect that. Do you have a more specific code sample we can use to discuss?

I can’t provide my UI code, but I can share the style update functions I have for both v6 and v7. I also have quite a few objects that need to be updated by the style refresh. What metric will have the most effect on the speed? Number of objects, number of styles, number of updated style elements?

My UI is basically monochrome using a color display, so you can change the primary color, but it updates all elements with the new primary color.

v6 update code:

void updateUIColor(uint8_t r, uint8_t g, uint8_t b, bool invert)
{
	lv_color_t fColor;
	lv_color_t bColor;

	if (invert)
	{
		bColor = LV_COLOR_MAKE(r, g, b);
		fColor = LV_COLOR_BLACK;
	}
	else
	{
		fColor = LV_COLOR_MAKE(r, g, b);
		bColor = LV_COLOR_BLACK;
	}

#if defined LVGL_DRIVER_DEBUG
	long startTime = micros();
#endif

	style_color_text_lg.text.color = fColor;
	style_color_text_lg.body.main_color = bColor;
	style_color_text_lg.body.grad_color = bColor;
	lv_obj_report_style_mod(&style_color_text_lg);

	style_color_text_small.text.color = fColor;
	lv_obj_report_style_mod(&style_color_text_small);

	style_box_no_border.text.color = fColor;
	style_box_no_border.body.main_color = bColor;
	style_box_no_border.body.grad_color = bColor;
	lv_obj_report_style_mod(&style_box_no_border);

	style_box_rounded.text.color = fColor;
	style_box_rounded.body.border.color = fColor;
	style_box_rounded.body.main_color = bColor;
	style_box_rounded.body.grad_color = bColor;
	lv_obj_report_style_mod(&style_box_rounded);

	style_box_square.text.color = fColor;
	style_box_square.body.border.color = fColor;
	style_box_square.body.main_color = bColor;
	style_box_square.body.grad_color = bColor;
	lv_obj_report_style_mod(&style_box_square);

	style_box_rounded_thick.text.color = fColor;
	style_box_rounded_thick.body.border.color = fColor;
	style_box_rounded_thick.body.main_color = bColor;
	style_box_rounded_thick.body.grad_color = bColor;
	lv_obj_report_style_mod(&style_box_rounded_thick);

	style_box_rounded_inv.body.border.color = fColor;
	style_box_rounded_inv.body.main_color = fColor;
	style_box_rounded_inv.body.grad_color = fColor;
	style_box_rounded_inv.text.color = bColor;
	lv_obj_report_style_mod(&style_box_rounded_inv);

	style_box_square_cell.body.main_color = fColor;
	style_box_square_cell.body.grad_color = fColor;
	style_box_square_cell.body.border.color = fColor;
	style_box_square_cell.text.color = bColor;
	lv_obj_report_style_mod(&style_box_square_cell);

	style_black_text_small_back.text.color = fColor;
	lv_obj_report_style_mod(&style_black_text_small_back);

	style_box_halftone_fill.body.main_color = fColor;
	style_box_halftone_fill.body.grad_color = fColor;
	style_box_halftone_fill.text.color = bColor;
	lv_obj_report_style_mod(&style_box_halftone_fill);

	style_line_dash.line.color = fColor;
	lv_obj_report_style_mod(&style_line_dash);

	style_line_dash_alt.line.color = fColor;
	lv_obj_report_style_mod(&style_line_dash_alt);

	style_line_dotted.line.color = fColor;
	lv_obj_report_style_mod(&style_line_dotted);

	style_box_unsel.body.main_color = bColor;
	style_box_unsel.body.grad_color = bColor;
	style_box_unsel.text.color = fColor;
	lv_obj_report_style_mod(&style_box_unsel);

	style_box_sel.body.main_color = fColor;
	style_box_sel.body.grad_color = fColor;
	style_box_sel.text.color = bColor;
	lv_obj_report_style_mod(&style_box_sel);

	style_black_text_sm.text.color = bColor;
	lv_obj_report_style_mod(&style_black_text_sm);

	style_color_text_small_back.text.color = bColor;
	lv_obj_report_style_mod(&style_color_text_small_back);

#if defined LVGL_DRIVER_DEBUG
	long stopTime = micros() - startTime;
	debug_console.println("STYLE REFRESH:%d", stopTime);
#endif

}

v7 update code:

void updateUIColor(uint8_t r, uint8_t g, uint8_t b, bool invert)
{
	lv_color_t fColor;
	lv_color_t bColor;

	if (invert)
	{
		bColor = LV_COLOR_MAKE(r, g, b);
		fColor = LV_COLOR_BLACK;
	}
	else
	{
		fColor = LV_COLOR_MAKE(r, g, b);
		bColor = LV_COLOR_BLACK;
	}

#if defined LVGL_DRIVER_DEBUG
	long startTime = micros();
#endif

	lv_style_set_bg_color(&black_bg, LV_STATE_DEFAULT, bColor);
	lv_style_set_text_color(&black_bg, LV_STATE_DEFAULT, fColor);
	lv_style_set_border_color(&black_bg, LV_STATE_DEFAULT, fColor);
	lv_style_set_line_color(&black_bg, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&black_bg);

	lv_style_set_line_color(&style_line_dash, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&style_line_dash);

	lv_style_set_line_color(&style_line_dash_alt, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&style_line_dash_alt);

	lv_style_set_line_color(&style_line_dotted, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&style_line_dotted);

	lv_style_set_text_color(&style_color_text_small, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&style_color_text_small);

	lv_style_set_text_color(&style_color_text_lg, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&style_color_text_lg);

	lv_style_set_border_color(&style_box_rounded, LV_STATE_DEFAULT, fColor);
	lv_style_set_bg_color(&style_box_rounded, LV_STATE_DEFAULT, bColor);
	lv_obj_report_style_mod(&style_box_rounded);

	lv_style_set_border_color(&style_box_rounded_thick, LV_STATE_DEFAULT, fColor);
	lv_style_set_bg_color(&style_box_rounded_thick, LV_STATE_DEFAULT, bColor);
	lv_obj_report_style_mod(&style_box_rounded_thick);

	lv_style_set_border_color(&style_box_square, LV_STATE_DEFAULT, fColor);
	lv_style_set_bg_color(&style_box_square, LV_STATE_DEFAULT, bColor);
	lv_obj_report_style_mod(&style_box_square);

	lv_style_set_bg_color(&style_box_halftone_fill, LV_STATE_DEFAULT, fColor);
	lv_obj_report_style_mod(&style_box_halftone_fill);

	lv_style_set_bg_color(&style_box_square_cell, LV_STATE_DEFAULT, fColor);
	lv_style_set_text_color(&style_box_square_cell, LV_STATE_DEFAULT, bColor);
	lv_obj_report_style_mod(&style_box_square_cell);

	lv_style_set_bg_color(&style_box_rounded_inv, LV_STATE_DEFAULT, fColor);
	lv_style_set_text_color(&style_box_rounded_inv, LV_STATE_DEFAULT, bColor);
	lv_obj_report_style_mod(&style_box_rounded_inv);

	lv_style_set_text_color(&style_color_text_small_back, LV_STATE_DEFAULT, bColor);
	lv_obj_report_style_mod(&style_color_text_small_back);

#if defined LVGL_DRIVER_DEBUG
	long stopTime = micros() - startTime;
	debug_console.println("STYLE REFRESH:%d", stopTime);
#endif
}

(cc @kisvegabor)

Can you reorder the code so that all the lv_style_set calls are grouped together and all the lv_obj_report_style_mod calls are grouped? That way you can measure the time it takes for each group to run. I suspect that the reporting of style modifications is the culprit here; the same objects may be getting invalidated multiple times.

OK, I rearranged them. Here are the separated results:

v6 style update (microseconds):

STYLE SET:2
STYLE REPORT:5751

v7 style update (microseconds):

STYLE SET:46
STYLE REPORT:143481

Also, I counted the objects being updated in the UI, there are 338 objects, none of them have multiple styles applied (v7).

Looks like my guess was correct. Your problem here isn’t even the rendering time - it seems that a lot of CPU cycles are being spent simply on invalidation. This looks like a bug - invalidation shouldn’t be this expensive.

EDIT: Opened a GitHub issue here.

Thanks for testing that out, I will keep an eye on the issue.