From 3329beef660f4722548e22a854a74b8572ebaee3 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 10 Dec 2019 19:20:49 +0900 Subject: [PATCH] evas ector: applied some memory buffer cache mechanism. This is a local memory pool mechanism to optimize the filter performance. I observed there are a lot of volatile memory allocations each frames, By using memory pool we can avoid huge memory allocations that brings filter performance up to about 30%. --- src/lib/evas/canvas/evas_render.c | 4 +- .../evas/engines/gl_generic/evas_ector_gl.h | 3 + .../engines/gl_generic/evas_ector_gl_buffer.c | 161 ++++++++++-------- .../evas/engines/gl_generic/evas_engine.c | 5 + 4 files changed, 100 insertions(+), 73 deletions(-) diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 5a627a34ba..0aea82793a 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -3289,7 +3289,6 @@ evas_render_updates_internal(Evas *eo_e, #ifdef EVAS_RENDER_DEBUG_TIMING double start_time = _time_get(); #endif - double time1, time2; double taccum = 0.06; time1 = _ttime_get(); @@ -3806,8 +3805,7 @@ evas_render_updates_internal(Evas *eo_e, #endif time2 = _ttime_get(); - taccum = (taccum + (time2 - time1)) * 0.5; - ERR("elapsed = %f", taccum); + ERR("elapsed = %f", time2 - time1); if (!do_async) _evas_render_cleanup(); eina_evlog("-render_end", eo_e, 0.0, NULL); diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl.h b/src/modules/evas/engines/gl_generic/evas_ector_gl.h index 6e4c46e5fc..5a48292337 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl.h +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl.h @@ -29,6 +29,9 @@ #include "evas_ector_gl_buffer.eo.h" #include "evas_ector_gl_image_buffer.eo.h" +void tizen_vd_ecache_init(); +void tizen_vd_ecache_term(); + #undef EAPI #define EAPI diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c index 2c6c745566..638bc94eea 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c @@ -20,82 +20,110 @@ typedef struct _Evas_Ector_GL_Buffer_Data Evas_Ector_GL_Buffer_Data; static int _map_id = 0; -typedef struct _Buffer_Cache +//////////////////////////////////////////////////////////////////////// +/* OPTIMIZATION: A Basic Cache Buffer to save memory allocations. */ +/* This first-aid method is applied for VD caption text filter effect */ +//////////////////////////////////////////////////////////////////////// +typedef struct _Ector_Cache_Buffer { - char *buffer; + void *buffer; int len; - Eina_Bool use; -} Buffer_Cache; + Eina_Bool use : 1; +} Ector_Cache_Buffer; -//////////////////////////////////////////////////////////////////////////////////////////////// -Buffer_Cache _buffer_cache[20]; -static int _ector_cnt = 0; +#define BUFFER_CNT 40 +static Eina_Inarray *_ecache_list; -char * _ector_buffer_get(int len) +void +tizen_vd_ecache_init() { - for (int i = 0; i < 10; i++) + _ecache_list = eina_inarray_new(sizeof(Ector_Cache_Buffer), 10); + + //Why 40? a experimental number of text filters. + eina_inarray_resize(_ecache_list, 40); +} + +void +tizen_vd_ecache_term() +{ + Ector_Cache_Buffer *ecb; + EINA_INARRAY_FOREACH(_ecache_list, ecb) + free(ecb->buffer); + + eina_inarray_free(_ecache_list); + _ecache_list = NULL; +} + +static void * +_ecache_buffer_request(int len, Eina_Bool clear) +{ + //Get Requested size + Ector_Cache_Buffer *ecb; + EINA_INARRAY_FOREACH(_ecache_list, ecb) { - if (_buffer_cache[i].use) continue; - if (_buffer_cache[i].len == 0) + if (ecb->use) continue; + + //Get a new buffer + if (ecb->len == 0) { - _buffer_cache[i].use = 1; - _buffer_cache[i].buffer = malloc(len); - _buffer_cache[i].len = len; - printf("malloc = %d\n", len); - return _buffer_cache[i].buffer; + len = (int)(((float) len) * 1.25f); + ecb->use = EINA_TRUE; + ecb->buffer = malloc(len); + ecb->len = len; + if (clear) memset(ecb->buffer, 0x0, len); + return ecb->buffer; } - if (_buffer_cache[i].len >= len) + //Get an idle buffer + if (ecb->len >= len) { - _buffer_cache[i].use = 1; - return _buffer_cache[i].buffer; + ecb->use = EINA_TRUE; + if (clear) memset(ecb->buffer, 0x0, ecb->len); + return ecb->buffer; } - else - { - free(_buffer_cache[i].buffer); - _buffer_cache[i].use = 1; - _buffer_cache[i].buffer = malloc(len); - _buffer_cache[i].len = len; - printf("malloc = %d\n", len); - return _buffer_cache[i].buffer; - } - printf("What?!\n"); + //Get an idle buffer after resizing + len = (int)(((float) len) * 1.25f); + ecb->buffer = realloc(ecb->buffer, len); + ecb->use = EINA_TRUE; + ecb->len = len; + if (clear) memset(ecb->buffer, 0x0, len); + return ecb->buffer; } - return NULL; + //Need to push a new item + Ector_Cache_Buffer necb; + len = (int)(((float) len) * 1.25f); + necb.use = EINA_TRUE; + necb.buffer = malloc(len); + if (clear) memset(necb.buffer, 0x0, len); + necb.len = len; + eina_inarray_push(_ecache_list, &necb); + + return necb.buffer; } -void _ector_buffer_return(char *buffer) +static Eina_Bool +_ecache_buffer_return(void *buffer) { - for (int i = 0; i < 10; i++) + //Get Requested size + Ector_Cache_Buffer *ecb; + + EINA_INARRAY_FOREACH(_ecache_list, ecb) { - if (_buffer_cache[i].buffer == buffer) + if (ecb->buffer == buffer) { - _buffer_cache[i].use = 0; - return; + ecb->use = EINA_FALSE; + return EINA_TRUE; } } - printf("What?!\n"); + + printf("what?!\n"); + return EINA_FALSE; } - -static void _ector_buffer_term() -{ - for (int i = 0; i < 10; i++) - { - free(_buffer_cache[i].buffer); - _buffer_cache[i].buffer = NULL; - _buffer_cache[i].use = 0; - _buffer_cache[i].len = 0; - } -} - -static void _ector_buffer_init() -{ -} -/////////////////////////////////////////////////////////////////////////////////////////////// - - +//////////////////////////////////////////////////////////////////////// +/* End of OPTIMIZATION */ +//////////////////////////////////////////////////////////////////////// struct _Ector_GL_Buffer_Map @@ -231,7 +259,7 @@ on_fail: evas_gl_common_image_free(pd->glim); pd->glim = NULL; */ - pd->image_data = calloc(1, w * h * 4); + pd->image_data = _ecache_buffer_request((w * h * 4), EINA_TRUE); pd->w = w; pd->h = h; pd->re = re; @@ -271,7 +299,7 @@ _image_get(Evas_Ector_GL_Buffer_Data *pd, Eina_Bool render) if (tofree) evas_gl_common_image_free(old_glim); - free(pd->image_data); + _ecache_buffer_return(pd->image_data); pd->image_data = NULL; } else @@ -433,8 +461,7 @@ _evas_ector_gl_buffer_ector_buffer_map(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buffer len = W * H; if (cspace == EFL_GFX_COLORSPACE_GRY8) { -// uint8_t *data8 = _ector_buffer_get(len); - uint8_t *data8 = malloc(len); + uint8_t *data8 = _ecache_buffer_request(len, EINA_FALSE); if (!data8) goto on_fail; _pixels_argb_to_gry8_convert(data8, data, len); map->allocated = EINA_TRUE; @@ -532,7 +559,7 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff if (pd->image_data != map->image_data) { - free(pd->image_data); + _ecache_buffer_return(pd->image_data); pd->image_data = map->image_data; } @@ -547,7 +574,7 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff if (pd->image_data != map->image_data) { - free(pd->image_data); + _ecache_buffer_return(pd->image_data); pd->image_data = map->image_data; } @@ -601,7 +628,7 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff if (pd->image_data != map->image_data) { - free(pd->image_data); + _ecache_buffer_return(pd->image_data); pd->image_data = map->image_data; } @@ -614,7 +641,7 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff } if (map->allocated) { - free(map->base_data); + _ecache_buffer_return(map->base_data); } free(map); return; @@ -625,13 +652,8 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff } EOLIAN static Efl_Object * -_evas_ector_gl_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_Buffer_Data *pd) +_evas_ector_gl_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_Buffer_Data *pd EINA_UNUSED) { - if (_ector_cnt == 0) - _ector_buffer_init(); - - ++_ector_cnt; -// printf("ector_cnt = %d", _ector_cnt); /* TIZEN_ONLY(20181130): evas ector - create a gl image when only it is going to be used if (!pd->glim) { @@ -646,10 +668,9 @@ _evas_ector_gl_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_Buffer_Data *pd EOLIAN static void _evas_ector_gl_buffer_efl_object_destructor(Eo *obj, Evas_Ector_GL_Buffer_Data *pd) { - --_ector_cnt; evas_gl_common_image_free(pd->glim); /* TIZEN_ONLY(20181130): evas ector - create a gl image when only it is going to be used */ - free(pd->image_data); + _ecache_buffer_return(pd->image_data); pd->image_data = NULL; /* END */ efl_destructor(efl_super(obj, MY_CLASS)); diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 202ce6a8d7..6ff94139fb 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -3340,12 +3340,17 @@ module_open(Evas_Module *em) /* now advertise out own api */ em->functions = (void *)(&func); + + tizen_vd_ecache_init(); + return 1; } static void module_close(Evas_Module *em EINA_UNUSED) { + tizen_vd_ecache_term(); + ector_shutdown(); if (_evas_engine_GL_log_dom >= 0) {