From a96fb28295887fa0c5ebf9dbc937eb3ff9ebc1a8 Mon Sep 17 00:00:00 2001 From: raster Date: Tue, 5 May 2009 14:37:18 +0000 Subject: [PATCH] more todo items knocked off for cserve git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@40509 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/bin/Makefile.am | 12 +-- src/bin/evas_cserve_main.c | 196 ++++++++++++++++++++++++++++++++++++++-- src/bin/evas_cserve_test_main.c | 33 ------- src/bin/evas_cserve_tool.c | 101 +++++++++++++++++++++ src/lib/cserve/evas_cs.h | 87 ++++++++++++------ src/lib/cserve/evas_cs_client.c | 56 +++++++++++- 6 files changed, 407 insertions(+), 78 deletions(-) delete mode 100644 src/bin/evas_cserve_test_main.c create mode 100644 src/bin/evas_cserve_tool.c diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 76c7aa8..84dedfa 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -19,7 +19,7 @@ AM_CPPFLAGS = \ AM_CFLAGS = @WIN32_CFLAGS@ -bin_PROGRAMS = evas_cserve evas_cserve_test +bin_PROGRAMS = evas_cserve evas_cserve_tool evas_cserve_SOURCES = \ evas_cserve_main.c @@ -27,14 +27,14 @@ evas_cserve_main.c evas_cserve_LDADD = \ $(top_builddir)/src/lib/libevas.la -evas_cserve_test_LDFLAGS = +evas_cserve_tool_LDFLAGS = -evas_cserve_test_SOURCES = \ -evas_cserve_test_main.c +evas_cserve_tool_SOURCES = \ +evas_cserve_tool.c -evas_cserve_test_LDADD = \ +evas_cserve_tool_LDADD = \ $(top_builddir)/src/lib/libevas.la -evas_cserve_test_LDFLAGS = +evas_cserve_tool_LDFLAGS = endif diff --git a/src/bin/evas_cserve_main.c b/src/bin/evas_cserve_main.c index db10194..2500b8d 100644 --- a/src/bin/evas_cserve_main.c +++ b/src/bin/evas_cserve_main.c @@ -1,11 +1,15 @@ #include "Evas.h" #include "evas_cs.h" #include +#include +#include +#ifdef _WIN32 +# include +#endif // fixme:'s // -// add ops to get/set cache size, check time and cache time (both) -// add ops to get internal state (both) +// 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) // @@ -35,6 +39,10 @@ struct _Img time_t modtime; time_t last_stat; } file; + struct { + int load1saved, load2saved; + double load1, load2; + } stats; Lopt load_opts; struct { int w, h; @@ -57,12 +65,116 @@ static Eina_List *cache_images = NULL; static int cache_usage = 0; static int cache_max_usage = 1 * 1024 * 1024; static int cache_item_timeout = -1; -static int cache_item_timeout_check = 10; +static int cache_item_timeout_check = -1; static Mem *stat_mem = NULL; static int stat_mem_num = 0; static Eina_List *stat_mems = NULL; +#ifndef _WIN32 +static double +get_time(void) +{ + struct timeval timev; + + gettimeofday(&timev, NULL); + return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000); +} +#else +static double +get_time(void) +{ + return (double)GetTickCount()/1000.0; +} +#endif + + +static int stats_dirty = 0; +static int saved_loads = 0; +static double saved_load_time = 0; +static double saved_load_lifetime = 0; + +static int saved_loaddatas = 0; +static double saved_loaddata_time = 0; +static double saved_loaddata_lifetime = 0; + +static int saved_memory = 0; +static int saved_memory_peak = 0; +static int alloced_memory = 0; +static int alloced_memory_peak = 0; +static int real_memory = 0; +static int real_memory_peak = 0; + +static Eina_Bool +stats_hash_image_cb(const Eina_Hash *hash __UNUSED__, + const void *key __UNUSED__, + void *data, void *fdata __UNUSED__) +{ + Img *img = data; + + saved_load_time += img->stats.load1 * img->stats.load1saved; + saved_loaddata_time += img->stats.load2 * img->stats.load2saved; + if (img->ref > 1) + saved_memory += img->image.w * img->image.h * sizeof(DATA32) * (img->ref - 1); + if (img->mem) + { + alloced_memory += img->image.w * img->image.h * sizeof(DATA32); + real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12; + } + return 1; +} + +static void +stats_calc(void) +{ + Img *img; + Eina_List *l; + + if (!stats_dirty) return; + stats_dirty = 0; + saved_loads = 0; + saved_load_time = 0; + saved_loaddatas = 0; + saved_loaddata_time = 0; + saved_memory = 0; + alloced_memory = 0; + real_memory = 0; + + if (active_images) + eina_hash_foreach(active_images, stats_hash_image_cb, NULL); + EINA_LIST_FOREACH(cache_images, l, img) + { + saved_loads += img->stats.load1saved; + saved_load_time += img->stats.load1 * img->stats.load1saved; + saved_loaddatas += img->stats.load2saved; + saved_loaddata_time += img->stats.load2 * img->stats.load2saved; + if (img->mem) + { + alloced_memory += img->image.w * img->image.h * sizeof(DATA32); + real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12; + } + } + if (saved_memory > saved_memory_peak) + saved_memory_peak = saved_memory; + if (real_memory > real_memory_peak) + real_memory_peak = real_memory; + if (alloced_memory > alloced_memory_peak) + alloced_memory_peak = alloced_memory; +} + +static void +stats_update(void) +{ + stats_dirty = 1; +} + +static void +stats_lifetime_update(Img *img) +{ + saved_load_lifetime += img->stats.load1 * img->stats.load1saved; + saved_loaddata_lifetime += img->stats.load2 * img->stats.load2saved; +} + static void stat_clean(Mem *m) { @@ -279,12 +391,16 @@ img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const int ret; Image_Entry *ie; int err = 0; + double t; ret = stat(file, &st); if (ret < 0) return NULL; + t = get_time(); ie = evas_cache_image_request(cache, file, key, load_opts, &err); + t = get_time() - t; if (!ie) return NULL; img = (Img *)ie; + img->stats.load1 = t; img->key = eina_stringshare_add(bufkey); img->file.modtime = st.st_mtime; img->file.file = eina_stringshare_add(file); @@ -309,8 +425,13 @@ img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const static void 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; + img->stats.load2 = t; if (img->image.data) msync(img->image.data, img->image.w * img->image.h * sizeof(DATA32), MS_SYNC | MS_INVALIDATE); img->usage += @@ -321,6 +442,8 @@ img_loaddata(Img *img) static void img_free(Img *img) { + stats_lifetime_update(img); + stats_update(); eina_stringshare_del(img->key); eina_stringshare_del(img->file.file); eina_stringshare_del(img->file.key); @@ -437,7 +560,9 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts) img = eina_hash_find(active_images, buf); if ((img) && (img_ok(img))) { + img->stats.load1saved++; img->ref++; + stats_update(); return img; } @@ -448,9 +573,11 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts) { if (img_ok(img)) { + img->stats.load1saved++; img->ref++; cache_images = eina_list_remove_list(cache_images, l); eina_hash_direct_add(active_images, img->key, img); + stats_update(); return img; } } @@ -546,6 +673,8 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * msg.mem.id = img->mem->id; msg.mem.offset = img->mem->offset; msg.mem.size = img->mem->size; + img->stats.load2saved++; + stats_update(); } else msg.mem.id = msg.mem.offset = msg.mem.size = 0; @@ -574,12 +703,16 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * Op_Loaddata *rep; Op_Loaddata_Reply msg; Img *img; -// fixme: handle loadopts on loaddata -// RGBA_Image_Loadopts lopt = {0, 0.0, 0, 0}; rep = (Op_Loaddata *)data; img = rep->handle; - img_loaddata(img); + if (img->mem) + { + img->stats.load2saved++; + stats_update(); + } + else + img_loaddata(img); memset(&msg, 0, sizeof(msg)); if (img->mem) { @@ -614,6 +747,57 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * img_forcedunload(img); } break; + case OP_GETCONFIG: + { + Op_Getconfig_Reply msg; + + msg.cache_max_usage = cache_max_usage; + msg.cache_item_timeout = cache_item_timeout; + msg.cache_item_timeout_check = cache_item_timeout_check; + evas_cserve_client_send(c, OP_GETCONFIG, sizeof(msg), (unsigned char *)(&msg)); + } + break; + case OP_SETCONFIG: + { + Op_Setconfig *rep; + + rep = (Op_Setconfig *)data; + cache_max_usage = rep->cache_max_usage; + cache_item_timeout = rep->cache_item_timeout; + cache_item_timeout_check = rep->cache_item_timeout_check; + cache_clean(); + } + break; + case OP_GETSTATS: + { + Op_Getstats_Reply msg; + + stats_calc(); + msg.saved_memory = saved_memory; + msg.wasted_memory = (real_memory - alloced_memory); + msg.saved_memory_peak = saved_memory_peak; + msg.wasted_memory_peak = (real_memory_peak - alloced_memory_peak); + msg.saved_time_image_header_load = saved_load_lifetime + saved_load_time; + msg.saved_time_image_data_load = saved_loaddata_lifetime + saved_loaddata_time; + evas_cserve_client_send(c, OP_GETSTATS, sizeof(msg), (unsigned char *)(&msg)); + } + break; + case OP_GETINFO: + { +// get a list of all images in active hash and cache list, and their info like +// file + key +// width, height and alpha flag +// refcount +// data loaded flag +// active ot cached +// last active timestamp +// dead +// mod time +// last checked mod time time +// memory footprint +// Op_Getstats_Reply msg; + } + break; default: break; } diff --git a/src/bin/evas_cserve_test_main.c b/src/bin/evas_cserve_test_main.c deleted file mode 100644 index 8a72705..0000000 --- a/src/bin/evas_cserve_test_main.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "evas_cs.h" - -int -main(int argc, char **argv) -{ - evas_init(); - - printf("evas_cserve_init = %i\n", evas_cserve_init()); - - { - Image_Entry *ie; - RGBA_Image_Loadopts lopt = { 0, 0.0, 0, 0}; - - ie = malloc(sizeof(Image_Entry)); - if (evas_cserve_image_load(ie, argv[1], NULL, &lopt)) - { - printf("load ok\n"); - if (evas_cserve_image_data_load(ie)) - { - Mem *m; - - m = ie->data2; - printf("first pixel: %08x\n", *((int *)m->data)); - printf("load data ok\n"); -// evas_cserve_image_free(ie); - } - } - } - - evas_cserve_shutdown(); - evas_shutdown(); - return 0; -} diff --git a/src/bin/evas_cserve_tool.c b/src/bin/evas_cserve_tool.c new file mode 100644 index 0000000..7d10865 --- /dev/null +++ b/src/bin/evas_cserve_tool.c @@ -0,0 +1,101 @@ +#include "evas_cs.h" + +int +main(int argc, char **argv) +{ + int i; + + evas_init(); + if (!evas_cserve_init()) + { + printf("ERROR: Cannot connect to cserve. abort\n"); + exit(-1); + } + + for (i = 1; i < argc; i++) + { + if ((!strcmp(argv[i], "-h")) || + (!strcmp(argv[i], "-help")) || + (!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" + ); + exit(0); + } + else if ((!strcmp(argv[i], "getconfig"))) + { + Op_Getconfig_Reply config; + + if (!evas_cserve_config_get(&config)) + { + printf("ERROR: cannot fetch config.\n"); + exit(-1); + } + printf("csize: %i\n", config.cache_max_usage / 1024); + printf("ctime: %i\n", config.cache_item_timeout); + printf("ctimecheck: %i\n", config.cache_item_timeout_check); + printf("-OK-\n"); + } + else if ((!strcmp(argv[i], "setconfig")) && (i < (argc - 3))) + { + Op_Setconfig config; + + i++; + config.cache_max_usage = atoi(argv[i]) * 1024; + i++; + config.cache_item_timeout = atoi(argv[i]); + i++; + config.cache_item_timeout_check = atoi(argv[i]); + if (!evas_cserve_config_set(&config)) + { + printf("ERROR: cannot set config.\n"); + exit(-1); + } + } + else if ((!strcmp(argv[i], "getstats"))) + { + Op_Getstats_Reply stats; + + if (!evas_cserve_stats_get(&stats)) + { + printf("ERROR: cannot fetch stats.\n"); + exit(-1); + } + printf("saved_memory: %i Kb\n", stats.saved_memory / 1024); + printf("wasted_memory: %i Kb\n", stats.wasted_memory / 1024); + printf("saved_memory_peak: %i Kb\n", stats.saved_memory_peak / 1024); + printf("wasted_memory_peak: %i Kb\n", stats.wasted_memory_peak / 1024); + printf("saved_time_image_header_load: %1.3f sec\n", stats.saved_time_image_header_load); + printf("saved_time_image_data_load: %1.3f sec\n", stats.saved_time_image_data_load); + printf("-OK-\n"); + } + } +/* + { + Image_Entry *ie; + RGBA_Image_Loadopts lopt = { 0, 0.0, 0, 0}; + + ie = malloc(sizeof(Image_Entry)); + if (evas_cserve_image_load(ie, argv[1], NULL, &lopt)) + { + printf("load ok\n"); + if (evas_cserve_image_data_load(ie)) + { + Mem *m; + + m = ie->data2; + printf("first pixel: %08x\n", *((int *)m->data)); + printf("load data ok\n"); +// evas_cserve_image_free(ie); + } + } + } + */ + evas_cserve_shutdown(); + evas_shutdown(); + return 0; +} diff --git a/src/lib/cserve/evas_cs.h b/src/lib/cserve/evas_cs.h index bc9ab39..a613190 100644 --- a/src/lib/cserve/evas_cs.h +++ b/src/lib/cserve/evas_cs.h @@ -92,35 +92,6 @@ struct _Mem }; //// for comms -// for clients to connect to cserve -EAPI Eina_Bool evas_cserve_init(void); -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_free(Image_Entry *ie); - -// for the server -EAPI Server *evas_cserve_server_add(void); -EAPI void evas_cserve_server_del(Server *s); -EAPI void evas_cserve_client_send(Client *c, int opcode, int size, unsigned char *data); -EAPI void evas_cserve_server_message_handler_set(Server *s, int (*func) (void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data), void *data); -EAPI void evas_cserve_server_wait(Server *s, int timeout); - -//// for memory -// for server -EAPI Mem *evas_cserve_mem_new(int size, const char *name); -EAPI void evas_cserve_mem_free(Mem *m); - -// for client -EAPI Mem *evas_cserve_mem_open(int pid, int id, const char *name, int size, int write); -EAPI void evas_cserve_mem_close(Mem *m); - -// for both -EAPI Eina_Bool evas_cserve_mem_resize(Mem *m, int size); -EAPI void evas_cserve_mem_del(int pid, int id); - - enum { OP_NOP, // 0 @@ -132,6 +103,11 @@ enum OP_PRELOAD, // 5 OP_FORCEDUNLOAD, // 6 + OP_GETCONFIG, // 7 + OP_SETCONFIG, // 8 + OP_GETSTATS, // 9 + OP_GETINFO, // 10 + OP_INVALID // 6 }; @@ -193,6 +169,59 @@ typedef struct { void *handle; } Op_Forcedunload; +typedef struct +{ + int cache_max_usage; + int cache_item_timeout; + int cache_item_timeout_check; +} Op_Getconfig_Reply; +typedef struct +{ + int cache_max_usage; + int cache_item_timeout; + int cache_item_timeout_check; +} Op_Setconfig; +typedef struct +{ + int saved_memory; + int wasted_memory; + int saved_memory_peak; + int wasted_memory_peak; + double saved_time_image_header_load; + double saved_time_image_data_load; +} Op_Getstats_Reply; + + +// for clients to connect to cserve +EAPI Eina_Bool evas_cserve_init(void); +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_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); +EAPI Eina_Bool evas_cserve_stats_get(Op_Getstats_Reply *stats); + +// for the server +EAPI Server *evas_cserve_server_add(void); +EAPI void evas_cserve_server_del(Server *s); +EAPI void evas_cserve_client_send(Client *c, int opcode, int size, unsigned char *data); +EAPI void evas_cserve_server_message_handler_set(Server *s, int (*func) (void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data), void *data); +EAPI void evas_cserve_server_wait(Server *s, int timeout); + +//// for memory +// for server +EAPI Mem *evas_cserve_mem_new(int size, const char *name); +EAPI void evas_cserve_mem_free(Mem *m); + +// for client +EAPI Mem *evas_cserve_mem_open(int pid, int id, const char *name, int size, int write); +EAPI void evas_cserve_mem_close(Mem *m); + +// for both +EAPI Eina_Bool evas_cserve_mem_resize(Mem *m, int size); +EAPI void evas_cserve_mem_del(int pid, int id); #endif diff --git a/src/lib/cserve/evas_cs_client.c b/src/lib/cserve/evas_cs_client.c index d029eca..6a3ab43 100644 --- a/src/lib/cserve/evas_cs_client.c +++ b/src/lib/cserve/evas_cs_client.c @@ -194,7 +194,7 @@ evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_ Op_Load msg; Op_Load_Reply *rep; unsigned char *buf; - char fbuf[PATH_MAX], wd[PATH_MAX]; + char fbuf[PATH_MAX], wdb[PATH_MAX]; int flen, klen; int opcode; int size; @@ -210,13 +210,13 @@ evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_ msg.lopt.h = lopt->h; if (file[0] != '/') { - if (getcwd(wd, sizeof(wd))) + if (getcwd(wdb, sizeof(wdb))) { - snprintf(fbuf, "%s/%s", wd, file); + snprintf(fbuf, sizeof(buf), "%s/%s", wdb, file); file = fbuf; } } - if (!realpath(file, wd)) file = wd; + if (!realpath(file, wdb)) file = wdb; flen = strlen(file) + 1; klen = strlen(key) + 1; buf = malloc(sizeof(msg) + flen + klen); @@ -288,4 +288,52 @@ evas_cserve_image_free(Image_Entry *ie) ie->data1 = NULL; } +EAPI Eina_Bool +evas_cserve_config_get(Op_Getconfig_Reply *config) +{ + Op_Getconfig_Reply *rep; + int opcode; + int size; + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!server_send(cserve, OP_GETCONFIG, 0, NULL)) return 0; + rep = (Op_Getconfig_Reply *)server_read(cserve, &opcode, &size); + if ((rep) && (opcode == OP_GETCONFIG) && (size == sizeof(Op_Getconfig_Reply))) + { + memcpy(config, rep, sizeof(Op_Getconfig_Reply)); + return 1; + } + return 0; +} + +EAPI Eina_Bool +evas_cserve_config_set(Op_Setconfig *config) +{ + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!server_send(cserve, OP_SETCONFIG, sizeof(Op_Setconfig), (unsigned char *)config)) return 0; + return 1; +} + +EAPI Eina_Bool +evas_cserve_stats_get(Op_Getstats_Reply *stats) +{ + Op_Getstats_Reply *rep; + int opcode; + int size; + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!server_send(cserve, OP_GETSTATS, 0, NULL)) return 0; + rep = (Op_Getstats_Reply *)server_read(cserve, &opcode, &size); + if ((rep) && (opcode == OP_GETSTATS) && (size == sizeof(Op_Getstats_Reply))) + { + memcpy(stats, rep, sizeof(Op_Getstats_Reply)); + return 1; + } + return 0; +} + #endif -- 2.7.4