From 88dd66f3d15b6839a7e64a672c73e9d4a352c9aa Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 28 Apr 2020 14:35:26 +0900 Subject: [PATCH] canvas clip: replace hash to cached array. Each child_map_across_mark() takes 0.026ms with eina_hash we can reduce the performing time by replacing the hash to array to 0.0041ms in a device. Before Average: 0.026ms Mostly it takes 23 times in the scrolling. thus it takes 3%(0.48ms) in one frame rendering (16ms) After Average: 0.0041ms Mostly it takes 23 times in the scrolling. thus it takes 0.6%(0.096ms) in one frame rendering (16ms) result: map calc 5x faster than original (0.384ms improved) Thanks Subhransu for report this. @optimization --- src/lib/evas/canvas/evas_clip.c | 27 ++++++++++++++------------- src/lib/evas/canvas/evas_main.c | 3 +++ src/lib/evas/canvas/evas_render.c | 3 +++ src/lib/evas/include/evas_private.h | 1 + 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/lib/evas/canvas/evas_clip.c b/src/lib/evas/canvas/evas_clip.c index 210aa5fc7d..55ecdb2179 100644 --- a/src/lib/evas/canvas/evas_clip.c +++ b/src/lib/evas/canvas/evas_clip.c @@ -74,30 +74,30 @@ evas_object_recalc_clippees(Evas_Object_Protected_Data *obj) #define MAP_ACROSS 1 static void -evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *map_obj, Eina_Bool force, Eina_Hash *visited) +evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *map_obj, Eina_Bool force, Eina_Array* visited) { #ifdef MAP_ACROSS Eina_Bool clear_visited = EINA_FALSE; - if (!visited) { - visited = eina_hash_pointer_new(NULL); + visited = &obj->layer->evas->map_clip_objects; clear_visited = EINA_TRUE; } - if (eina_hash_find(visited, &eo_obj) == (void *)1) goto end; - else eina_hash_add(visited, &eo_obj, (void *)1); - + + if (eina_array_find(visited, (void*) eo_obj, NULL)) goto end; + else eina_array_push(visited, (void*) eo_obj); + if ((obj->map->cur.map_parent != map_obj) || force) { EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write) map_write->cur.map_parent = map_obj; EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write); - EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) - { - state_write->cache.clip.dirty = 1; - } - EINA_COW_STATE_WRITE_END(obj, state_write, cur); + EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) + { + state_write->cache.clip.dirty = 1; + } + EINA_COW_STATE_WRITE_END(obj, state_write, cur); evas_object_clip_recalc(obj); if (obj->is_smart) @@ -125,8 +125,9 @@ evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Dat } } } -end: - if (clear_visited) eina_hash_free(visited); + +end: + if (clear_visited) eina_array_clean(visited); #endif } diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c index fc53f64dc8..956e13dbcf 100644 --- a/src/lib/evas/canvas/evas_main.c +++ b/src/lib/evas/canvas/evas_main.c @@ -363,6 +363,8 @@ _evas_canvas_efl_object_constructor(Eo *eo_obj, Evas_Public_Data *e) EVAS_ARRAY_SET(e, glyph_unref_queue); EVAS_ARRAY_SET(e, texts_unref_queue); + eina_array_step_set(&e->map_clip_objects, sizeof(e->map_clip_objects), 64); + e->active_objects.version = EINA_ARRAY_VERSION; eina_inarray_step_set(&e->active_objects, sizeof(Eina_Inarray), @@ -644,6 +646,7 @@ _evas_canvas_efl_object_destructor(Eo *eo_e, Evas_Public_Data *e) eina_array_flush(&e->image_unref_queue); eina_array_flush(&e->glyph_unref_queue); eina_array_flush(&e->texts_unref_queue); + eina_array_flush(&e->map_clip_objects); eina_hash_free(e->focused_objects); SLKL(e->post_render.lock); diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 4a44c5e6ea..1d47ba06af 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -4127,6 +4127,7 @@ _evas_canvas_render_idle_flush(Eo *eo_e, Evas_Public_Data *evas) OBJS_ARRAY_FLUSH(&evas->delete_objects); OBJS_ARRAY_FLUSH(&evas->obscuring_objects); OBJS_ARRAY_FLUSH(&evas->temporary_objects); + OBJS_ARRAY_FLUSH(&evas->map_clip_objects); eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL); eina_array_clean(&evas->clip_changes); @@ -4243,6 +4244,7 @@ if (Cow) while (eina_cow_gc(Cow)) OBJS_ARRAY_FLUSH(&evas->delete_objects); OBJS_ARRAY_FLUSH(&evas->obscuring_objects); OBJS_ARRAY_FLUSH(&evas->temporary_objects); + OBJS_ARRAY_FLUSH(&evas->map_clip_objects); eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL); eina_array_clean(&evas->clip_changes); @@ -4268,6 +4270,7 @@ evas_render_invalidate(Evas *eo_e) OBJS_ARRAY_FLUSH(&e->delete_objects); OBJS_ARRAY_FLUSH(&e->snapshot_objects); + OBJS_ARRAY_FLUSH(&e->map_clip_objects); e->invalidate = EINA_TRUE; } diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 036ef71ca9..3a24821dd2 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -453,6 +453,7 @@ struct _Evas_Public_Data Eina_Array image_unref_queue; Eina_Array glyph_unref_queue; Eina_Array texts_unref_queue; + Eina_Array map_clip_objects; Eina_List *finalize_objects; struct {