EFL Optimization: Optimizing Tizen Native Applications
This tutorial demonstrates how you can optimize your Tizen native application.
Warm-up
Become familiar with the Edje, Elementary, and Evas API basics by learning about:
-
Optimizing EDC
Optimize the EDC code.
-
Optimizing Evas
Optimize the Evas code.
Optimizing EDC
To optimize EDC:
- Remove unnecessary parts.
When you create EDC, there can be obsolete and unnecessary parts. Since they have an effect on performance, remove them.
Before After collections { group { name: "main"; parts { part { name: "bg"; type: RECT; description { state: "default" 0.0; rel1.relative: 0.0 0.0; rel2.relative: 1.0 1.0; color: 255 255 255 255; } } part { name: "new"; type: RECT; scale: 1; mouse_events: 1; description { state: "default" 0.0; color: 255 255 0 255; rel1.relative: 0.2 0.2; rel2.relative: 0.8 0.8; } } part { name: "old"; type: RECT; scale: 1; mouse_events: 1; description { state: "default" 0.0; color: 0 0 0 0; rel1.relative: 0.5 0.5; rel2.relative: 1.0 1.0; } } } } }
collections { group { name: "main"; parts { part { name: "bg"; type: RECT; description { state: "default" 0.0; rel1.relative: 0.0 0.0; rel2.relative: 1.0 1.0; color: 255 255 255 255; } } part { name: "new"; type: RECT; scale: 1; mouse_events: 1; description { state: "default" 0.0; color: 255 255 0 255; rel1.relative: 0.2 0.2; rel2.relative: 0.8 0.8; } } } } }
- Use Text, if possible, instead of Textblock.
The following EDCs lead to the same result. However, use TEXT for the simple texts for high performance apart from using tags or multiple lines.
Before After collections { styles { style { name: "text_style"; base: "font="Sans" font_size=30 text_class=entry color=#0088AA style=shadow,bottom shadow_color=#00000080 valign=0.5 ellipsis=1.0 wrap=none align=center"; } } group { name: "main"; parts { part { name: "text"; type: TEXTBLOCK; scale: 1; description { state: "default" 0.0; text { style: "text_style"; text: "TEXT"; } } } } } }
collections { group { name: "main"; part { name: "simple"; type: TEXT; scale: 1; effect: SHADOW; description { state: "default" 0.0; align: 0.5 0.5; color: 0 136 170 255; visible: 1; text { size: 30; font: "Sans"; text: "TEXT"; } } } } }
- Compress images and embed your images into EDC.
When you use a fixed image, it is more efficient to call an image within EDC. This save time in accessing the image data and is more suitable for the data size.
collections { images { image: "logo.png" COMP; } group { name: "main"; parts { part { name: "logo"; type: IMAGE; description { state: "default" 0.0; rel1.relative: 0.0 0.0; rel2.relative: 1.0 1.0; image.normal: "logo.png"; aspect: 1 1; aspect_preference: BOTH; } } } } }
- Use a SPACER part, if possible.
When you use a part (such as Padding) which is invisible but has a size, using Spacer is more efficient. Since Spacer is invisible, it does not have the visible and color options.
Before After collections { group { name: "main"; parts { part { name: "bg"; type: RECT; description { state: "default" 0.0; color: 255 255 255 255; } } part { name: "padding_left_top"; type: RECT; description { state: "default" 0.0; color: 0 0 0 0; rel1.to: "bg"; rel2.to:"bg"; rel2.relative: 0.0 0.0; align: 0.0 0.0; min: 100 100; } } part { name: "padding_right_bottom"; type: RECT; description { state: "default" 0.0; color: 0 0 0 0; rel1.to: "bg"; rel1.relative: 1.0 1.0; rel2.to:"bg"; align: 1.0 1.0; min: 100 100; } } part { name: "content"; type: RECT; description { state: "default" 0.0; color: 255 255 0 255; rel1.to: "padding_left_top"; rel1.relative: 1.0 1.0; rel2.to:"padding_right_bottom"; rel2.relative: 0.0 0.0; } } } } }
collections { group { name: "main"; parts { part { name: "bg"; type: RECT; description { state: "default" 0.0; color: 255 255 255 255; } } part { name: "padding_left_top"; type: SPACER; description { state: "default" 0.0; rel1.to: "bg"; rel2.to:"bg"; rel2.relative: 0.0 0.0; align: 0.0 0.0; min: 100 100; } } part { name: "padding_right_bottom"; type: SPACER; description { state: "default" 0.0; rel1.to: "bg"; rel1.relative: 1.0 1.0; rel2.to:"bg"; align: 1.0 1.0; min: 100 100; } } part { name: "content"; type: RECT; description { state: "default" 0.0; color: 255 255 0 255; rel1.to: "padding_left_top"; rel1.relative: 1.0 1.0; rel2.to:"padding_right_bottom"; rel2.relative: 0.0 0.0; } } } } }
- Use the image border feature.
When you use an image, you do not need to use a full size or larger size image. As you can see below, it is much more efficient to scale the image using a border option.
Before After collections { images { image: "test.png" COMP; } group { name: "main"; parts { part { name: "test"; type: IMAGE; description { state: "default" 0.0; rel1.relative: 0.2 0.2; rel2.relative: 0.8 0.8; image.normal: "test.png"; } } } } }
collections { images { image: "test.png" COMP; } group { name: "main"; parts { part { name: "test"; type: IMAGE; description { state: "default" 0.0; rel1.relative: 0.2 0.2; rel2.relative: 0.8 0.8; image.normal: "test.png"; image.border: 5 5 5 5; } } } } }
Optimizing Evas
To optimize Evas:
- Use a rectangle object instead of using a solid color image.
When you need a solid color object, it is better (more efficient) to use a rectangle object than the image.
Before image = elm_image_add(win); snprintf(buf, sizeof(buf), "%s/images/white_bg.png", elm_app_data_dir_get()); elm_image_file_set(image, buf, NULL); evas_object_size_hint_weight_set(image, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, image); evas_object_show(image);
After rect = evas_object_rectangle_add(evas_object_evas_get(win)); evas_object_color_set(rect, 255, 255, 255, 255); evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, rect); evas_object_show(rect);
- Make an object invisible instead of setting alpha as 0.
To make an object invisible, it is more efficient to use evas_object_hide() instead of changing the alpha value to 0.
Before After static void _invisible_cb(void *data, Evas_Object *obj, void *ev) { evas_object_color_set(obj, 0, 0, 0, 0); }
static void _invisible_cb(void *data, Evas_Object *obj, void *ev) { evas_object_hide(obj); }
- If you need maximum optimization, use evas_object_image instead of elm_image and elm_icon.
Before img = elm_image_add((parent); snprintf(buf, sizeof(buf), "%s/images/white_bg.png", elm_app_data_dir_get()); elm_image_file_set(img, buf, NULL); evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(img);
After img = evas_object_image_add(evas_object_evas_get(parent)); snprintf(buf, sizeof(buf), "%s/images/white_bg.png", elm_app_data_dir_get()); evas_object_image_file_set(img, buf, NULL); evas_object_image_filled_set(img, EINA_TRUE); evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(img);
- Set the parent correctly to avoid the elementary tree reconstruction.
Before creating an object, make sure that the relationship between parent and child is set correctly to avoid having to reconstruct later.
Before After win = elm_win_add(); scroller = elm_scroller_add(win); box = elm_box_add(win); button = elm_button_add(win);
win = elm_win_add(); scroller = elm_scroller_add(win); box = elm_box_add(scroller); button = elm_button_add(box);