From d92a6d99a7a6add1fb1e4e1b021dfca2f6f97eb7 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Wed, 6 May 2009 12:36:06 +0000 Subject: [PATCH] more cserver work for sharede cache- improvements SVN revision: 40524 --- legacy/evas/src/bin/evas_cserve_main.c | 115 ++++++++++++++++-- legacy/evas/src/bin/evas_cserve_tool.c | 12 +- legacy/evas/src/lib/cserve/evas_cs.h | 22 ++-- legacy/evas/src/lib/cserve/evas_cs_client.c | 35 +++++- .../src/lib/engines/common/evas_image_main.c | 14 ++- .../engines/common/evas_image_scalecache.c | 104 +++++++++++++--- 6 files changed, 260 insertions(+), 42 deletions(-) diff --git a/legacy/evas/src/bin/evas_cserve_main.c b/legacy/evas/src/bin/evas_cserve_main.c index 2500b8d1de..6b9caf4827 100644 --- a/legacy/evas/src/bin/evas_cserve_main.c +++ b/legacy/evas/src/bin/evas_cserve_main.c @@ -11,7 +11,7 @@ // // add ops to get internal cache state (both) // preload - make it work (both) -// monitor /proc/meminfo and if mem low - free items until cache empty (server) + // // pants! @@ -29,6 +29,7 @@ struct _Img { Image_Entry ie; int ref; + int dref; int usage; Mem *mem; const char *key; @@ -51,6 +52,7 @@ struct _Img } image; Eina_Bool dead : 1; Eina_Bool active : 1; + Eina_Bool useless : 1; }; // config @@ -63,7 +65,8 @@ static Evas_Cache_Image *cache = NULL; static Eina_Hash *active_images = NULL; static Eina_List *cache_images = NULL; static int cache_usage = 0; -static int cache_max_usage = 1 * 1024 * 1024; +static int cache_max_usage = 1 * 1024; +static int cache_max_adjust = 0; static int cache_item_timeout = -1; static int cache_item_timeout_check = -1; static Mem *stat_mem = NULL; @@ -88,6 +91,35 @@ get_time(void) } #endif +static int mem_total = 0; +static int mem_free = 0; +static int mem_buffers = 0; +static int mem_cached = 0; + +static void +meminfo_check(void) +{ + FILE *f; + char buf[1024]; + int v; + + f = fopen("/proc/meminfo", "r"); + if (!f) return; + if (!fgets(buf, sizeof(buf), f)) goto done; + v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done; + mem_total = v; + if (!fgets(buf, sizeof(buf), f)) goto done; + v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done; + mem_free = v; + if (!fgets(buf, sizeof(buf), f)) goto done; + v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done; + mem_buffers = v; + if (!fgets(buf, sizeof(buf), f)) goto done; + v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done; + mem_cached = v; + done: + fclose(f); +} static int stats_dirty = 0; static int saved_loads = 0; @@ -427,7 +459,6 @@ img_loaddata(Img *img) { double t; - // fixme: load img data t = get_time(); evas_cache_image_load_data((Image_Entry *)img); t = get_time() - t; @@ -453,7 +484,7 @@ img_free(Img *img) static void cache_clean(void) { - while ((cache_usage > cache_max_usage) && (cache_images)) + while ((cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) && (cache_images)) { Img *img; Eina_List *l; @@ -486,6 +517,26 @@ cache_timeout(time_t t) } } +static void +mem_cache_adjust(void) +{ + int pval = cache_max_adjust; + int max = 0; + + if (mem_total <= 0) return; + if ((mem_free + mem_cached + mem_buffers) < mem_total) + cache_max_adjust += mem_total - (mem_free + mem_cached + mem_buffers); + + max = (mem_free / 8) - cache_max_usage; + if (max < 0) max = 0; + if (max > cache_max_usage) max = cache_max_usage; + cache_max_adjust = max - cache_max_usage; + + if (cache_max_adjust < -cache_max_usage) + cache_max_adjust = -cache_max_usage; + if (pval != cache_max_adjust) cache_clean(); +} + static void img_cache(Img *img) { @@ -499,7 +550,7 @@ img_cache(Img *img) cache_images = eina_list_prepend(cache_images, img); img->cached = t_now; cache_usage += img->usage; - if (cache_usage > cache_max_usage) + if (cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) cache_clean(); } @@ -595,6 +646,31 @@ img_unload(Img *img) } } +static void +img_unloaddata(Img *img) +{ + if ((img->dref <= 0) && (img->useless)) + { + Image_Entry *ie = (Image_Entry *)img; + + evas_cserve_mem_free(img->mem); + img->mem = NULL; + img->image.data = NULL; + img->dref = 0; + + ie->flags.loaded = 0; + ie->allocated.w = 0; + ie->allocated.h = 0; + } +} + +static void +img_useless(Img *img) +{ + img->useless = 1; + if (img->dref <= 0) img_unloaddata(img); +} + static void img_forcedunload(Img *img) { @@ -725,6 +801,28 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); } break; + case OP_UNLOADDATA: + { + Op_Unloaddata *rep; + Img *img; + + rep = (Op_Unloaddata *)data; + img = rep->handle; + img->dref--; + img_unloaddata(img); + } + break; + case OP_USELESSDATA: + { + Op_Unloaddata *rep; + Img *img; + + rep = (Op_Unloaddata *)data; + img = rep->handle; + img->dref--; + img_useless(img); + } + break; case OP_PRELOAD: { Op_Preload *rep; @@ -825,7 +923,7 @@ parse_args(int argc, char **argv) else if ((!strcmp(argv[i], "-csize")) && (i < (argc - 1))) { i++; - cache_max_usage = atoi(argv[i]) * 1024; + cache_max_usage = atoi(argv[i]); } else if ((!strcmp(argv[i], "-ctime")) && (i < (argc - 1))) { @@ -954,18 +1052,19 @@ main(int argc, char **argv) if (exit_flag) break; t = time(NULL); t_next = t - last_check; - if ((t_next) > cache_item_timeout_check) + if ((t_next) >= cache_item_timeout_check) { t_next = cache_item_timeout_check; last_check = t; cache_timeout(t); + meminfo_check(); + mem_cache_adjust(); } if ((t_next <= 0) && (cache_item_timeout_check > 0)) t_next = 1; } error: - printf("clean shutdown\n"); if (stat_mem) { stat_clean(stat_mem); diff --git a/legacy/evas/src/bin/evas_cserve_tool.c b/legacy/evas/src/bin/evas_cserve_tool.c index 7d10865c28..ffeb3f9862 100644 --- a/legacy/evas/src/bin/evas_cserve_tool.c +++ b/legacy/evas/src/bin/evas_cserve_tool.c @@ -19,10 +19,10 @@ main(int argc, char **argv) (!strcmp(argv[i], "--help"))) { printf("Options:\n" - "\t-h This help\n" - "\tgetconfig Get configuration values\n" - "\tsetconfig csize ctimeout ctimecheck Set the config values\n" - "\tgetstats Get current cache statistics\n" + "\t-h This help\n" + "\tgetconfig Get configuration values\n" + "\tsetconfig CSIZE CTIME CTIMECHECK Set the config values\n" + "\tgetstats Get current cache statistics\n" ); exit(0); } @@ -35,7 +35,7 @@ main(int argc, char **argv) printf("ERROR: cannot fetch config.\n"); exit(-1); } - printf("csize: %i\n", config.cache_max_usage / 1024); + printf("csize: %i\n", config.cache_max_usage); printf("ctime: %i\n", config.cache_item_timeout); printf("ctimecheck: %i\n", config.cache_item_timeout_check); printf("-OK-\n"); @@ -45,7 +45,7 @@ main(int argc, char **argv) Op_Setconfig config; i++; - config.cache_max_usage = atoi(argv[i]) * 1024; + config.cache_max_usage = atoi(argv[i]); i++; config.cache_item_timeout = atoi(argv[i]); i++; diff --git a/legacy/evas/src/lib/cserve/evas_cs.h b/legacy/evas/src/lib/cserve/evas_cs.h index a613190265..ea7fb87c42 100644 --- a/legacy/evas/src/lib/cserve/evas_cs.h +++ b/legacy/evas/src/lib/cserve/evas_cs.h @@ -100,15 +100,17 @@ enum OP_LOAD, // 2 OP_UNLOAD, // 3 OP_LOADDATA, // 4 - OP_PRELOAD, // 5 - OP_FORCEDUNLOAD, // 6 + OP_UNLOADDATA, // 5 + OP_USELESSDATA, // 6 + OP_PRELOAD, // 7 + OP_FORCEDUNLOAD, // 8 - OP_GETCONFIG, // 7 - OP_SETCONFIG, // 8 - OP_GETSTATS, // 9 - OP_GETINFO, // 10 + OP_GETCONFIG, // 9 + OP_SETCONFIG, // 10 + OP_GETSTATS, // 11 + OP_GETINFO, // 12 - OP_INVALID // 6 + OP_INVALID // 13 }; typedef struct @@ -141,6 +143,10 @@ typedef struct void *handle; } Op_Unload; typedef struct +{ + void *handle; +} Op_Unloaddata; +typedef struct { void *handle; } Op_Loaddata; @@ -198,6 +204,8 @@ EAPI int evas_cserve_use_get(void); EAPI void evas_cserve_shutdown(void); EAPI Eina_Bool evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt); EAPI Eina_Bool evas_cserve_image_data_load(Image_Entry *ie); +EAPI void evas_cserve_image_unload(Image_Entry *ie); +EAPI void evas_cserve_image_useless(Image_Entry *ie); EAPI void evas_cserve_image_free(Image_Entry *ie); EAPI Eina_Bool evas_cserve_config_get(Op_Getconfig_Reply *config); EAPI Eina_Bool evas_cserve_config_set(Op_Setconfig *config); diff --git a/legacy/evas/src/lib/cserve/evas_cs_client.c b/legacy/evas/src/lib/cserve/evas_cs_client.c index 6a3ab43cdd..d04631d9a6 100644 --- a/legacy/evas/src/lib/cserve/evas_cs_client.c +++ b/legacy/evas/src/lib/cserve/evas_cs_client.c @@ -282,12 +282,43 @@ evas_cserve_image_free(Image_Entry *ie) if (ie->data1 == NULL) return; memset(&msg, 0, sizeof(msg)); msg.handle = ie->data1; - if (ie->data2) evas_cserve_mem_close(ie->data2); - ie->data2 = NULL; + if (ie->data2) evas_cserve_image_unload(ie); server_send(cserve, OP_UNLOAD, sizeof(msg), (unsigned char *)(&msg)); ie->data1 = NULL; } +EAPI void +evas_cserve_image_unload(Image_Entry *ie) +{ + Op_Unloaddata msg; + + if (csrve_init > 0) server_reinit(); + else return; + if (!cserve) return; + if (ie->data1 == NULL) return; + memset(&msg, 0, sizeof(msg)); + msg.handle = ie->data1; + if (ie->data2) evas_cserve_mem_close(ie->data2); + ie->data2 = NULL; + server_send(cserve, OP_UNLOADDATA, sizeof(msg), (unsigned char *)(&msg)); +} + +EAPI void +evas_cserve_image_useless(Image_Entry *ie) +{ + Op_Unloaddata msg; + + if (csrve_init > 0) server_reinit(); + else return; + if (!cserve) return; + if (ie->data1 == NULL) return; + memset(&msg, 0, sizeof(msg)); + msg.handle = ie->data1; + if (ie->data2) evas_cserve_mem_close(ie->data2); + ie->data2 = NULL; + server_send(cserve, OP_USELESSDATA, sizeof(msg), (unsigned char *)(&msg)); +} + EAPI Eina_Bool evas_cserve_config_get(Op_Getconfig_Reply *config) { diff --git a/legacy/evas/src/lib/engines/common/evas_image_main.c b/legacy/evas/src/lib/engines/common/evas_image_main.c index 00976ac3ec..0640ee794f 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_main.c +++ b/legacy/evas/src/lib/engines/common/evas_image_main.c @@ -173,8 +173,9 @@ evas_common_rgba_image_unload(Image_Entry *ie) evas_cache_image_preload_cancel(ie, NULL); if (!ie->flags.loaded) return; - if (!ie->info.module) return; + if ((!ie->info.module) && (!ie->data1)) return; if (!ie->file) return; + ie->flags.loaded = 0; if ((im->cs.data) && (im->image.data)) @@ -190,6 +191,17 @@ evas_common_rgba_image_unload(Image_Entry *ie) } im->cs.data = NULL; +#ifdef EVAS_CSERVE + if (ie->data1) + { + evas_cserve_image_useless(ie); + im->image.data = NULL; + ie->allocated.w = 0; + ie->allocated.h = 0; + return; + } +#endif + if (im->image.data && !im->image.no_free) free(im->image.data); im->image.data = NULL; diff --git a/legacy/evas/src/lib/engines/common/evas_image_scalecache.c b/legacy/evas/src/lib/engines/common/evas_image_scalecache.c index 473d698fce..76cf5ff5cb 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_scalecache.c +++ b/legacy/evas/src/lib/engines/common/evas_image_scalecache.c @@ -12,13 +12,13 @@ #define MAX_SCALEITEMS 32 #define MIN_SCALE_USES 3 -#define MIN_SCALE_AGE_GAP 5000 -#define MIN_SCALECACHE_SIZE 3200 +//#define MIN_SCALE_AGE_GAP 5000 +#define MAX_SCALECACHE_DIM 3200 #define FLOP_ADD 4 #define MAX_FLOP_COUNT 16 #define FLOP_DEL 1 -//#define SCALE_CACHE_SIZE 10 * 1024 * 1024 -#define SCALE_CACHE_SIZE 0 +#define SCALE_CACHE_SIZE 4 * 1024 * 1024 +//#define SCALE_CACHE_SIZE 0 typedef struct _Scaleitem Scaleitem; @@ -30,7 +30,11 @@ struct _Scaleitem RGBA_Image *im, *parent_im; int src_x, src_y, src_w, src_h; int dst_w, dst_h; - int smooth, populate_me, flop; + int flop; + int size_adjust; + Eina_Bool forced_unload : 1; + Eina_Bool smooth : 1; + Eina_Bool populate_me : 1; }; #ifdef SCALECACHE @@ -96,7 +100,10 @@ evas_common_rgba_image_scalecache_dirty(Image_Entry *ie) // printf(" 0- %i\n", sci->dst_w * sci->dst_h * 4); LKL(cache_lock); evas_common_rgba_image_free(&sci->im->cache_entry); - cache_size -= sci->dst_w * sci->dst_h * 4; + if (!sci->forced_unload) + cache_size -= sci->dst_w * sci->dst_h * 4; + else + cache_size -= sci->size_adjust; cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci); LKU(cache_lock); } @@ -201,7 +208,10 @@ _sci_find(RGBA_Image *im, if (sci->im) { evas_common_rgba_image_free(&sci->im->cache_entry); - cache_size -= sci->dst_w * sci->dst_h * 4; + if (!sci->forced_unload) + cache_size -= sci->dst_w * sci->dst_h * 4; + else + cache_size -= sci->size_adjust; // printf(" 1- %i\n", sci->dst_w * sci->dst_h * 4); cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci); } @@ -252,7 +262,10 @@ _cache_prune(Scaleitem *notsci, Evas_Bool copies_only) sci->usage = 0; sci->usage_count = 0; sci->flop += FLOP_ADD; - cache_size -= sci->dst_w * sci->dst_h * 4; + if (!sci->forced_unload) + cache_size -= sci->dst_w * sci->dst_h * 4; + else + cache_size -= sci->size_adjust; // printf(" 2- %i\n", sci->dst_w * sci->dst_h * 4); cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci); memset(sci, 0, sizeof(Eina_Inlist)); @@ -344,8 +357,8 @@ evas_common_rgba_image_scalecache_prepare(Image_Entry *ie, RGBA_Image *dst, { if (!sci->im) { - if ((sci->dst_w < MIN_SCALECACHE_SIZE) && - (sci->dst_h < MIN_SCALECACHE_SIZE)) + if ((sci->dst_w < MAX_SCALECACHE_DIM) && + (sci->dst_h < MAX_SCALECACHE_DIM)) { if (sci->flop <= MAX_FLOP_COUNT) { @@ -389,6 +402,7 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst, RGBA_Image *im = (RGBA_Image *)ie; Scaleitem *sci; int didpop = 0; + int dounload = 0; /* static int i = 0; @@ -456,6 +470,44 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst, } return; } + if (sci->populate_me) + { + int size, osize, used; + + size = dst_region_w * dst_region_h; + if (((dst_region_w > 640) || (dst_region_h > 640)) && + (size > (480 * 480))) + { + Eina_List *l; + Scaleitem *sci2; + + dounload = 1; + osize = sci->parent_im->cache_entry.w * sci->parent_im->cache_entry.h; + used = 0; + EINA_LIST_FOREACH(im->cache.list, l, sci2) + { + if (sci2->im) used += sci2->dst_w * sci2->dst_h; + } + if ((size < osize) && (used == 0)) + sci->size_adjust = 0; + else + { + osize -= used; + if (osize < 0) osize = 0; + size -= osize; + sci->size_adjust = size * 4; + } + } + else + { + size *= sizeof(DATA32); + if ((cache_size + size) > max_cache_size) + { + sci->populate_me = 0; + im->cache.populate_count--; + } + } + } if (sci->populate_me) { // printf("##! populate!\n"); @@ -510,11 +562,11 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst, { if (yy & 0x1) { - if (xx & 0x1) *pp = 0; + if (xx & 0x1) *pp = 0x882288ff; } else { - if (!(xx & 0x1)) *pp = 0; + if (!(xx & 0x1)) *pp = 0x882288ff; } pp++; } @@ -522,7 +574,15 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst, } #endif } - cache_size += sci->dst_w * sci->dst_h * 4; + if (dounload) + { + sci->forced_unload = 1; + cache_size += sci->size_adjust; + } + else + { + cache_size += sci->dst_w * sci->dst_h * 4; + } // printf(" + %i @ flop: %i (%ix%i)\n", // sci->dst_w * sci->dst_h * 4, sci->flop, // sci->dst_w, sci->dst_h); @@ -555,12 +615,20 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst, // im, // (int)im->cache.orig_usage, // (int)im->cache.newest_usage); - if ((im->cache_entry.flags.loaded) && (!im->cs.no_free) && - (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)) + if ((dounload) || + ((im->cache_entry.flags.loaded) && + ((!im->cs.no_free) +#ifdef EVAS_CSERVE + || (ie->data1) +#endif + ) && + (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888))) { - if (im->cache.orig_usage < - (im->cache.newest_usage / 20)) - evas_common_rgba_image_unload(&im->cache_entry); + if ((dounload) || (im->cache.orig_usage < + (im->cache.newest_usage / 20))) + { + evas_common_rgba_image_unload(&im->cache_entry); + } } LKU(im->cache.lock); }