textblock/optimization: refactor evas_textblock_style for memory and perfromance.

the main user of textblock_style_set() api is the edje whcih keeps its owen edje_textblock_style
tags( string_shared string) by changing the textblock to keep the string_shared string will improve
the chance of sharing the same string hence reducing memory.

By removing the Eina_StrBuf usage inside the loop in textblock_style_set() api we can avoid lot
of temporary memory allocation and deallocation hence will improve performance.

Note: I see lot of places we use Eina_Strbuf inside a loop (eina_strbuf_new() does 2 allocation)
We need to be extra carefull while reviewing when the code uses those construct to see if its really necessary.

Data: it reduces memory allocation by 7000 in elementary_test launch time.

Reviewed-by: Cedric BAIL <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D9545
This commit is contained in:
subhransu mohanty 2019-08-12 02:42:27 +00:00 committed by Cedric BAIL
parent 384765b088
commit 9952b9bf18
1 changed files with 20 additions and 37 deletions

View File

@ -307,8 +307,8 @@ typedef struct _Text_Item_Filter Text_Item_Filter;
struct _Evas_Object_Style_Tag_Base struct _Evas_Object_Style_Tag_Base
{ {
char *tag; /**< Format Identifier: b=Bold, i=Italic etc. */ const char *tag; /**< Format Identifier: b=Bold, i=Italic etc. */
char *replace; /**< Replacement string. "font_weight=Bold", "font_style=Italic" etc. */ const char *replace; /**< Replacement string. "font_weight=Bold", "font_style=Italic" etc. */
size_t tag_len; /**< Strlen of tag. */ size_t tag_len; /**< Strlen of tag. */
}; };
@ -552,7 +552,7 @@ struct _Evas_Object_Textblock_Format
struct _Efl_Canvas_Text_Style struct _Efl_Canvas_Text_Style
{ {
const char *style_text; const char *style_text;
char *default_tag; const char *default_tag;
Evas_Object_Style_Tag *tags; Evas_Object_Style_Tag *tags;
Eina_List *objects; Eina_List *objects;
Eina_Bool delete_me : 1; Eina_Bool delete_me : 1;
@ -874,15 +874,15 @@ static void
_style_replace(Evas_Textblock_Style *ts, const char *style_text) _style_replace(Evas_Textblock_Style *ts, const char *style_text)
{ {
eina_stringshare_replace(&ts->style_text, style_text); eina_stringshare_replace(&ts->style_text, style_text);
if (ts->default_tag) free(ts->default_tag); if (ts->default_tag) eina_stringshare_del(ts->default_tag);
while (ts->tags) while (ts->tags)
{ {
Evas_Object_Style_Tag *tag; Evas_Object_Style_Tag *tag;
tag = (Evas_Object_Style_Tag *)ts->tags; tag = (Evas_Object_Style_Tag *)ts->tags;
ts->tags = (Evas_Object_Style_Tag *)eina_inlist_remove(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag)); ts->tags = (Evas_Object_Style_Tag *)eina_inlist_remove(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag));
free(tag->tag.tag); eina_stringshare_del(tag->tag.tag);
free(tag->tag.replace); eina_stringshare_del(tag->tag.replace);
free(tag); free(tag);
} }
ts->default_tag = NULL; ts->default_tag = NULL;
@ -7319,6 +7319,7 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
key_start = key_stop = val_start = NULL; key_start = key_stop = val_start = NULL;
p = ts->style_text; p = ts->style_text;
Eina_Strbuf *tag_value_buf = eina_strbuf_new();
while (*p) while (*p)
{ {
if (!key_start) if (!key_start)
@ -7344,12 +7345,13 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
} }
if ((key_start) && (key_stop) && (val_start)) if ((key_start) && (key_stop) && (val_start))
{ {
char *tags, *replaces = NULL; const char *tag_value = NULL;
Evas_Object_Style_Tag *tag; Evas_Object_Style_Tag *tag;
const char *val_stop = NULL; const char *val_stop = NULL;
eina_strbuf_reset(tag_value_buf);
size_t tag_len; size_t tag_len;
{ {
Eina_Strbuf *buf = eina_strbuf_new();
val_stop = val_start; val_stop = val_start;
while(*p) while(*p)
{ {
@ -7358,72 +7360,53 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
/* Break if we found the tag end */ /* Break if we found the tag end */
if (p[-1] != '\\') if (p[-1] != '\\')
{ {
eina_strbuf_append_length(buf, val_stop, eina_strbuf_append_length(tag_value_buf, val_stop,
p - val_stop); p - val_stop);
break; break;
} }
else else
{ {
eina_strbuf_append_length(buf, val_stop, eina_strbuf_append_length(tag_value_buf, val_stop,
p - val_stop - 1); p - val_stop - 1);
eina_strbuf_append_char(buf, '\''); eina_strbuf_append_char(tag_value_buf, '\'');
val_stop = p + 1; val_stop = p + 1;
} }
} }
p++; p++;
} }
replaces = eina_strbuf_string_steal(buf);
eina_strbuf_free(buf);
} }
/* If we didn't find an end, just aboart. */ /* If we didn't find an end, just aboart. */
if (!*p) if (!*p)
{ {
if (replaces) free(replaces);
break; break;
} }
tag_len = key_stop - key_start; tag_len = key_stop - key_start;
tags = malloc(tag_len + 1); tag_value = eina_strbuf_string_get(tag_value_buf);
if (tags) if (tag_len && (tag_value))
{ {
memcpy(tags, key_start, tag_len); if (!strncmp(key_start, "DEFAULT", tag_len))
tags[tag_len] = 0;
}
if ((tags) && (replaces))
{ {
if (!strcmp(tags, "DEFAULT")) ts->default_tag = eina_stringshare_add(tag_value);
{
ts->default_tag = replaces;
free(tags);
} }
else else
{ {
tag = calloc(1, sizeof(Evas_Object_Style_Tag)); tag = calloc(1, sizeof(Evas_Object_Style_Tag));
if (tag) if (tag)
{ {
tag->tag.tag = tags; tag->tag.tag = eina_stringshare_add_length(key_start, tag_len);
tag->tag.replace = replaces; tag->tag.replace = eina_stringshare_add(tag_value);
tag->tag.tag_len = tag_len; tag->tag.tag_len = tag_len;
ts->tags = (Evas_Object_Style_Tag *)eina_inlist_append(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag)); ts->tags = (Evas_Object_Style_Tag *)eina_inlist_append(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag));
} }
else
{
free(tags);
free(replaces);
} }
} }
}
else
{
if (tags) free(tags);
if (replaces) free(replaces);
}
key_start = key_stop = val_start = NULL; key_start = key_stop = val_start = NULL;
} }
p++; p++;
} }
eina_strbuf_free(tag_value_buf);
} }
EINA_LIST_FOREACH(ts->objects, l, eo_obj) EINA_LIST_FOREACH(ts->objects, l, eo_obj)