summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_clip.c
diff options
context:
space:
mode:
authorVostokov Sergey <s.vostokov@samsung.com>2013-12-05 21:05:44 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-12-05 21:08:35 +0900
commit6a5e72d37b3cabca3fcb46d0817c3405b3f824a7 (patch)
treea943a5664a0a24873dcf20495bb074339b808eba /src/lib/evas/canvas/evas_clip.c
parent1ac5a89957b1f61fd5db1cac6ee329b0b028647f (diff)
evas - Clip mark performance improvement
stable release - cherry-pick me! We propose a patch that reduces graph traversal work in evas_object_child_map_across_mark(). It fixes a few particular slowdowns around Tizen applications, including 0.6 seconds slowdown. evas_object_child_map_across_mark() does not seem to need to recursively call itself on the same object many times. Yet we have noticed that in some scenarios it repeatedly traverses the same subtrees of objects over and over again, whenever there is more than one way of reaching these subtrees. In the production issue mentioned above, certain elm_object_part_content_set() call results in millions of recursive calls of evas_object_child_map_across_mark(), taking ~0.6sec total. We propose to allocate a hash table during top-level call to store all objects visited, and return from sub-calls instantly whenever we are called over an object we already visited.
Diffstat (limited to '')
-rw-r--r--src/lib/evas/canvas/evas_clip.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/src/lib/evas/canvas/evas_clip.c b/src/lib/evas/canvas/evas_clip.c
index 76cddc0301..a3f7480d0f 100644
--- a/src/lib/evas/canvas/evas_clip.c
+++ b/src/lib/evas/canvas/evas_clip.c
@@ -73,9 +73,19 @@ evas_object_recalc_clippees(Evas_Object_Protected_Data *obj)
73 73
74#define MAP_ACROSS 1 74#define MAP_ACROSS 1
75static void 75static void
76evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *map_obj, Eina_Bool force) 76evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *map_obj, Eina_Bool force, Eina_Hash *visited)
77{ 77{
78#ifdef MAP_ACROSS 78#ifdef MAP_ACROSS
79 Eina_Bool clear_visited = EINA_FALSE;
80
81 if (!visited)
82 {
83 visited = eina_hash_pointer_new(NULL);
84 clear_visited = EINA_TRUE;
85 }
86 if (eina_hash_find(visited, &eo_obj) == (void *)1) return;
87 else eina_hash_direct_add(visited, &eo_obj, (void *)1);
88
79 if ((obj->map->cur.map_parent != map_obj) || force) 89 if ((obj->map->cur.map_parent != map_obj) || force)
80 { 90 {
81 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write) 91 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
@@ -98,7 +108,8 @@ evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Dat
98 // if obj has its own map - skip it. already done 108 // if obj has its own map - skip it. already done
99 if ((obj2->map->cur.map) && (obj2->map->cur.usemap)) continue; 109 if ((obj2->map->cur.map) && (obj2->map->cur.usemap)) continue;
100 Evas_Object *eo_obj2 = obj2->object; 110 Evas_Object *eo_obj2 = obj2->object;
101 evas_object_child_map_across_mark(eo_obj2, obj2, map_obj, force); 111 evas_object_child_map_across_mark(eo_obj2, obj2, map_obj,
112 force, visited);
102 } 113 }
103 } 114 }
104 else if (obj->clip.clipees) 115 else if (obj->clip.clipees)
@@ -108,10 +119,12 @@ evas_object_child_map_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_Dat
108 119
109 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2) 120 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2)
110 { 121 {
111 evas_object_child_map_across_mark(obj2->object, obj2, map_obj, force); 122 evas_object_child_map_across_mark(obj2->object, obj2,
123 map_obj, force, visited);
112 } 124 }
113 } 125 }
114 } 126 }
127 if (clear_visited) eina_hash_free(visited);
115#endif 128#endif
116} 129}
117 130
@@ -121,7 +134,8 @@ evas_object_clip_across_check(Evas_Object *eo_obj, Evas_Object_Protected_Data *o
121#ifdef MAP_ACROSS 134#ifdef MAP_ACROSS
122 if (!obj->cur->clipper) return; 135 if (!obj->cur->clipper) return;
123 if (obj->cur->clipper->map->cur.map_parent != obj->map->cur.map_parent) 136 if (obj->cur->clipper->map->cur.map_parent != obj->map->cur.map_parent)
124 evas_object_child_map_across_mark(eo_obj, obj, obj->map->cur.map_parent, 1); 137 evas_object_child_map_across_mark(eo_obj, obj, obj->map->cur.map_parent,
138 1, NULL);
125#endif 139#endif
126} 140}
127 141
@@ -134,9 +148,10 @@ evas_object_clip_across_clippees_check(Evas_Object *eo_obj, Evas_Object_Protecte
134 148
135 if (!obj->clip.clipees) return; 149 if (!obj->clip.clipees) return;
136// schloooooooooooow: 150// schloooooooooooow:
137// evas_object_child_map_across_mark(eo_obj, obj->map->cur.map_parent, 1); 151// evas_object_child_map_across_mark(eo_obj, obj->map->cur.map_parent, 1, NULL);
138// buggy: 152// buggy:
139 evas_object_child_map_across_mark(eo_obj, obj, obj->map->cur.map_parent, 0); 153 evas_object_child_map_across_mark(eo_obj, obj, obj->map->cur.map_parent, 0,
154 NULL);
140 if (obj->cur->cache.clip.dirty) 155 if (obj->cur->cache.clip.dirty)
141 { 156 {
142 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2) 157 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2)
@@ -156,7 +171,7 @@ evas_object_mapped_clip_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_D
156{ 171{
157#ifdef MAP_ACROSS 172#ifdef MAP_ACROSS
158 if ((obj->map->cur.map) && (obj->map->cur.usemap)) 173 if ((obj->map->cur.map) && (obj->map->cur.usemap))
159 evas_object_child_map_across_mark(eo_obj, obj, eo_obj, 0); 174 evas_object_child_map_across_mark(eo_obj, obj, eo_obj, 0, NULL);
160 else 175 else
161 { 176 {
162 if (obj->smart.parent) 177 if (obj->smart.parent)
@@ -164,10 +179,10 @@ evas_object_mapped_clip_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_D
164 Evas_Object_Protected_Data *smart_parent_obj = 179 Evas_Object_Protected_Data *smart_parent_obj =
165 eo_data_scope_get(obj->smart.parent, EVAS_OBJ_CLASS); 180 eo_data_scope_get(obj->smart.parent, EVAS_OBJ_CLASS);
166 evas_object_child_map_across_mark 181 evas_object_child_map_across_mark
167 (eo_obj, obj, smart_parent_obj->map->cur.map_parent, 0); 182 (eo_obj, obj, smart_parent_obj->map->cur.map_parent, 0, NULL);
168 } 183 }
169 else 184 else
170 evas_object_child_map_across_mark(eo_obj, obj, NULL, 0); 185 evas_object_child_map_across_mark(eo_obj, obj, NULL, 0, NULL);
171 } 186 }
172#endif 187#endif
173} 188}