more cserver work for sharede cache- improvements

SVN revision: 40524
This commit is contained in:
Carsten Haitzler 2009-05-06 12:36:06 +00:00
parent 63e4b4e564
commit d92a6d99a7
6 changed files with 260 additions and 42 deletions

View File

@ -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);

View File

@ -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++;

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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);
}