evas/cserve2: Fix cserve2_usage tool

Also, print shared arrays usage as it is sent as first message
upon connection to the server.

Add fonts to LRU and flush LRU as needed.
Seems to work okay. Could probably be finetuned a bit.
This commit is contained in:
Jean-Philippe Andre 2013-08-20 18:26:02 +09:00
parent df31807329
commit 1e4ee656a0
6 changed files with 255 additions and 491 deletions

View File

@ -352,6 +352,7 @@ const char *cserve2_shared_array_name_get(Shared_Array *sa);
void cserve2_shared_array_del(Shared_Array *sa);
int cserve2_shared_array_size_get(Shared_Array *sa);
int cserve2_shared_array_count_get(Shared_Array *sa);
int cserve2_shared_array_map_size_get(Shared_Array *sa);
int cserve2_shared_array_item_size_get(Shared_Array *sa);
int cserve2_shared_array_generation_id_get(Shared_Array *sa);
int cserve2_shared_array_size_set(Shared_Array *sa, int newcount);

View File

@ -1080,12 +1080,34 @@ _font_entry_key_hash(const Font_Entry *key, int key_length EINA_UNUSED)
return hash;
}
static int
_font_entry_memory_usage_get(Font_Entry *fe)
{
int size;
if (!fe) return 0;
if (!fe->mempool && !fe->glyph_datas)
return 0;
size = cserve2_shared_mempool_size_get(fe->mempool);
size += cserve2_shared_array_map_size_get(fe->glyph_datas);
size += fe->nglyphs * sizeof(Glyph_Entry);
return size;
}
static void
_font_entry_free(Font_Entry *fe)
{
Font_Data *fd;
int size;
if (!fe) return;
size = _font_entry_memory_usage_get(fe);
DBG("Font memory usage down: %d -> %d / %d", font_mem_usage,
font_mem_usage - size, max_font_usage);
font_mem_usage -= size;
fd = _font_data_find(fe->font_data_id);
if (fd)
@ -1098,6 +1120,7 @@ _font_entry_free(Font_Entry *fe)
fash_gl_free(fe->glyph_entries);
cserve2_shared_array_del(fe->glyph_datas);
cserve2_shared_mempool_del(fe->mempool);
cserve2_font_ft_free(fe->ft);
fe->src->refcount--;
if (fe->src->refcount <= 0)
@ -1141,79 +1164,49 @@ _font_source_free(Font_Source *fs)
free(fs);
}
#if 0
static void
_font_shm_promote(Font_Cache *fc)
_font_lru_update(Font_Entry *fe)
{
Eina_List *l;
l = eina_list_data_find_list(font_shm_lru, fc);
font_shm_lru = eina_list_demote_list(font_shm_lru, l);
}
static int
_font_shm_size_get(Font_Cache *fc)
{
int size;
size = sizeof(*fc) + cserve2_shm_size_get(fc->shm);
return size;
}
static void
_font_shm_free(Font_Cache *fc)
{
Glyph_Data *gd;
Font_Entry *fe = fc->fe;
unsigned int k;
fe->caches = eina_list_remove(fe->caches, fc);
if (fc == fe->last_cache)
fe->last_cache = NULL;
for (k = 0; k < fc->nglyphs; k++)
l = eina_list_data_find_list(font_shm_lru, fe);
if (l)
{
int *gldata_id = cserve2_shared_array_item_data_get(fc->glyphs, k);
gd = _glyph_data_find(*gldata_id);
fash_gl_del(fe->glyphs, gd->index);
if (fe->unused)
font_shm_lru = eina_list_promote_list(font_shm_lru, l);
else
font_shm_lru = eina_list_demote_list(font_shm_lru, l);
}
cserve2_shared_array_del(fc->glyphs);
cserve2_shm_unref(fc->shm);
free(fc);
if (!fe->caches)
eina_hash_del_by_key(font_entries, fe);
else
font_shm_lru = eina_list_append(font_shm_lru, fe);
}
static void
_font_shm_lru_flush(void)
_font_lru_flush(void)
{
Eina_List *l, *l_next;
l = font_shm_lru;
l_next = eina_list_next(l);
DBG("Font memory usage [begin]: %d / %d", font_mem_usage, max_font_usage);
while (l && font_mem_usage > max_font_usage)
{
int size;
Font_Cache *fc;
Font_Entry *fe;
fc = eina_list_data_get(l);
if (fc->fe->unused && fc->inuse == 0)
fe = eina_list_data_get(l);
if (fe->unused)
{
font_shm_lru = eina_list_remove_list(font_shm_lru, l);
size = _font_shm_size_get(fc);
size += fc->nglyphs * sizeof(Glyph_Entry);
_font_shm_free(fc);
font_mem_usage -= size;
eina_hash_del_by_key(font_entries, fe);
}
l = l_next;
l_next = eina_list_next(l);
}
DBG("Font memory usage [end]: %d / %d", font_mem_usage, max_font_usage);
}
#endif
void
cserve2_cache_init(void)
@ -1352,10 +1345,10 @@ _entry_reference_del(Entry *entry, Reference *ref)
}
else if (entry->type == CSERVE2_FONT_ENTRY)
{
Font_Entry *fe = (Font_Entry *)entry;
Font_Entry *fe = (Font_Entry *) entry;
fe->unused = EINA_TRUE;
if (!fe->mempool)
eina_hash_del_by_key(font_entries, fe);
_font_lru_update(fe);
_font_lru_flush();
}
else
ERR("Wrong type of entry.");
@ -1719,150 +1712,6 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
return (req->nanswer == req->nglyphs);
}
#if 0
/* organize answer (cache1{gl1, gl2,}, cache2{gl3,gl4,gl5}, cache3{gl6})
*/
static Eina_List *
_glyphs_group_create(Glyphs_Request *req)
{
Eina_List *groups = NULL;
unsigned int i;
Glyphs_Group *gg;
gg = calloc(1, sizeof(*gg));
groups = eina_list_append(groups, gg);
for (i = 0; i < req->nanswer; i++)
gg->glyphs = eina_list_append(gg->glyphs, req->answer[i]);
return groups;
/*
for (i = 0; i < req->nanswer; i++)
{
Eina_List *l;
Glyphs_Group *iter, *gg = NULL;
Font_Cache *fc = req->answer[i]->fc;
EINA_LIST_FOREACH(groups, l, iter)
{
if (iter->fc == fc)
{
gg = iter;
break;
}
}
if (!gg)
{
gg = calloc(1, sizeof(*gg));
gg->fc = fc;
groups = eina_list_append(groups, gg);
}
gg->glyphs = eina_list_append(gg->glyphs, req->answer[i]);
}
return groups;
*/
}
static Msg_Font_Glyphs_Loaded *
_glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
{
Msg_Font_Glyphs_Loaded msg;
unsigned int size;
Eina_List *ll, *answers = NULL;
const char *shmname;
unsigned int shmsize;
char *resp, *buf;
Glyphs_Group *iter;
memset(&msg, 0, sizeof(msg));
msg.base.type = CSERVE2_FONT_GLYPHS_LOADED;
answers = _glyphs_group_create(req);
msg.ncaches = eina_list_count(answers);
size = sizeof(msg);
// calculate size of message
// ncaches * sizeof(cache) + nglyphs1 * sizeof(glyph) +
// nglyphs2 * sizeof(glyph)...
EINA_LIST_FOREACH(answers, ll, iter)
{
shmname = cserve2_shm_name_get(iter->fc->shm);
shmsize = eina_stringshare_strlen(shmname) + 1;
// shm namelen + name
size += sizeof(int) + shmsize;
// nglyphs
size += sizeof(int);
// nglyphs * (index + offset + size + rows + width + pitch +
// num_grays + pixel_mode)
size += eina_list_count(iter->glyphs) * 9 * sizeof(int);
}
resp = malloc(size);
memcpy(resp, &msg, sizeof(msg));
buf = resp + sizeof(msg);
EINA_LIST_FREE(answers, iter)
{
Glyph_Entry *gl;
unsigned int nglyphs;
shmname = cserve2_shm_name_get(iter->fc->shm);
shmsize = eina_stringshare_strlen(shmname) + 1;
memcpy(buf, &shmsize, sizeof(int));
buf += sizeof(int);
memcpy(buf, shmname, shmsize);
buf += shmsize;
nglyphs = eina_list_count(iter->glyphs);
memcpy(buf, &nglyphs, sizeof(int));
buf += sizeof(int);
iter->fc->inuse -= eina_list_count(iter->glyphs);
EINA_LIST_FREE(iter->glyphs, gl)
{
// TODO: Factorize memcpy
Glyph_Data *gldata;
gldata = _glyph_data_find(gl->gldata_id);
memcpy(buf, &gldata->index, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->shm_id, sizeof(string_t));
buf += sizeof(string_t);
memcpy(buf, &gldata->offset, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->size, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->rows, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->width, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->pitch, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->num_grays, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->pixel_mode, sizeof(int));
buf += sizeof(int);
}
/* We are removing SHMs from the beginning of the list, so this
* gives a higher priority to them */
_font_shm_promote(iter->fc);
eina_list_free(iter->glyphs);
free(iter);
}
*resp_size = size;
return (Msg_Font_Glyphs_Loaded *)resp;
}
#endif
static Msg_Font_Glyphs_Loaded *
_glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
{
@ -2105,11 +1954,19 @@ _glyphs_load_request_response(Glyphs_Request *req,
if (!msg->nglyphs)
return _glyphs_loaded_msg_create(req, size);
DBG("Font memory usage [begin]: %d / %d", font_mem_usage, max_font_usage);
if (!mempool)
mempool = cserve2_shared_mempool_new(0);
{
mempool = cserve2_shared_mempool_new(0);
font_mem_usage += cserve2_shared_mempool_size_get(mempool);
}
if (!fe->glyph_datas)
fe->glyph_datas = cserve2_shared_array_new(1, sizeof(Glyph_Data), 0);
{
fe->glyph_datas = cserve2_shared_array_new(1, sizeof(Glyph_Data), 0);
font_mem_usage += cserve2_shared_array_map_size_get(fe->glyph_datas);
}
shm_id = cserve2_shared_string_add(cserve2_shared_mempool_name_get(mempool));
for (j = 0; j < msg->nglyphs; j++)
@ -2119,9 +1976,11 @@ _glyphs_load_request_response(Glyphs_Request *req,
gl = fash_gl_find(fe->glyph_entries, msg->glyphs[j].index);
if (!gl)
{
int glyph_id;
int glyph_id, orig_mapsize, new_mapsize;
Glyph_Data *gldata;
orig_mapsize = cserve2_shared_array_map_size_get(fe->glyph_datas);
glyph_id = cserve2_shared_array_item_new(fe->glyph_datas);
gldata = cserve2_shared_array_item_data_get(fe->glyph_datas,
glyph_id);
@ -2152,7 +2011,9 @@ _glyphs_load_request_response(Glyphs_Request *req,
fe->nglyphs++;
fash_gl_add(fe->glyph_entries, gldata->index, gl);
font_mem_usage += sizeof(*gl) + sizeof(*gldata);
new_mapsize = cserve2_shared_array_map_size_get(fe->glyph_datas);
font_mem_usage += new_mapsize - orig_mapsize;
font_mem_usage += sizeof(*gl);
}
req->answer[req->nanswer++] = gl;
}
@ -2169,6 +2030,9 @@ _glyphs_load_request_response(Glyphs_Request *req,
fe->mempool = mempool;
DBG("Font memory usage [end]: %d / %d", font_mem_usage, max_font_usage);
_font_lru_flush();
return _glyphs_loaded_msg_create(req, size);
}
@ -2185,42 +2049,39 @@ static Slave_Request_Funcs _glyphs_load_funcs = {
};
static Eina_Bool
_font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
_font_requested_size_cb(const Eina_Hash *hash EINA_UNUSED,
Glyph_Data *gldata, Msg_Stats *msg)
{
// FIXME TODO Must reimplement this
if (gldata->refcount)
msg->fonts.requested_size += gldata->size;
#if 0
return EINA_TRUE;
}
static Eina_Bool
_font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED,
const void *key EINA_UNUSED, void *data, void *fdata)
{
Font_Entry *fe = data;
Msg_Stats *msg = fdata;
Eina_List *iter;
Font_Cache *fc;
int nrefs = eina_list_count(fe->base.references);
unsigned int shmsize;
msg->fonts.fonts_loaded++;
if (fe->unused) msg->fonts.fonts_unused++;
// accounting size
EINA_LIST_FOREACH(fe->caches, iter, fc)
{
unsigned int fc_usage, shmsize;
/* This is not real requested usage, but an approximation. We don't
* know how many times each glyph would be used by each client, but
* assume that a similar set of glyphs from a given font would be used
* by each client, thus counting them one time per client referencing
* them.
*/
fc_usage = fc->usage * nrefs;
shmsize = cserve2_shm_size_get(fc->shm);
shmsize = cserve2_shared_mempool_size_get(fe->mempool);
msg->fonts.real_size += shmsize;
if (fe->unused) msg->fonts.unused_size += shmsize;
msg->fonts.requested_size += fc_usage;
msg->fonts.real_size += shmsize;
if (fe->unused) msg->fonts.unused_size += shmsize;
}
cserve2_shared_array_foreach(fe->glyph_datas,
EINA_EACH_CB(_font_requested_size_cb), msg);
#ifdef DEBUG_LOAD_TIME
// accounting fonts load time
msg->fonts.fonts_load_time += fe->base.load_time;
if (fe->caches)
if (fe->mempool)
{
msg->fonts.fonts_used_load_time += fe->base.load_time;
msg->fonts.fonts_used_saved_time += fe->base.saved_time;
@ -2232,8 +2093,6 @@ _font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
msg->fonts.glyphs_saved_time += fe->gl_saved_time;
msg->fonts.glyphs_request_time += fe->gl_request_time;
msg->fonts.glyphs_slave_time += fe->gl_slave_time;
#endif
#endif
return EINA_TRUE;
@ -2319,52 +2178,53 @@ struct _debug_info
};
static Eina_Bool
_font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
_font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED,
const void *key EINA_UNUSED, void *data, void *fdata)
{
struct _debug_info *di = fdata;
unsigned int size = di->size;
Font_Entry *fe = data;
const char *str;
// filelen
size += sizeof(int);
di->size+= sizeof(int);
// file
if (fe->src->file)
{
str = cserve2_shared_string_get(fe->src->file);
size += strlen(str) + 1;
di->size+= strlen(str) + 1;
}
// namelen
size += sizeof(int);
di->size+= sizeof(int);
// name
if (fe->src->name)
{
str = cserve2_shared_string_get(fe->src->file);
size += strlen(str) + 1;
di->size+= strlen(str) + 1;
}
// rend_flags, size, dpi
size += 3 * sizeof(int);
// rend_flags, size, dpi, unused
di->size+= 4 * sizeof(int);
// unused
size += sizeof(int);
// glyph_data_shm and glyph_mempool_shm (short strings)
di->size+= 2 * 64;
// ncaches
size += sizeof(int);
// nglyphs
di->size+= sizeof(int);
size += cserve2_shared_mempool_size_get(fe->mempool);
// glyphs
di->size+= fe->nglyphs * sizeof(Glyph_Data);
di->size = size;
di->nfonts++;
return EINA_TRUE;
}
static Eina_Bool
_font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
_font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED,
const void *key EINA_UNUSED, void *data, void *fdata)
{
char **pos = fdata;
char *buf = *pos;
@ -2451,124 +2311,6 @@ _font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
return EINA_TRUE;
}
// FIXME TODO Must reimplement this
#if 0
char **pos = fdata;
char *buf = *pos;
Font_Entry *fe = data;
Font_Cache *fc;
Eina_List *iter;
unsigned int len;
unsigned int unused;
unsigned int ncaches;
const char *str;
// filelen + file
len = 0;
if (fe->src->file)
{
str = cserve2_shared_string_get(fe->src->file);
len = strlen(str) + 1;
}
memcpy(buf, &len, sizeof(int));
buf += sizeof(int);
if (len) memcpy(buf, cserve2_shared_string_get(fe->src->file), len);
buf += len;
// namelen + name
len = 0;
if (fe->src->name)
{
str = cserve2_shared_string_get(fe->src->name);
len = strlen(str) + 1;
}
memcpy(buf, &len, sizeof(int));
buf += sizeof(int);
if (len) memcpy(buf, cserve2_shared_string_get(fe->src->name), len);
buf += len;
// rend_flags, size, dpi
memcpy(buf, &fe->rend_flags, sizeof(int));
buf += sizeof(int);
memcpy(buf, &fe->size, sizeof(int));
buf += sizeof(int);
memcpy(buf, &fe->dpi, sizeof(int));
buf += sizeof(int);
// unused
unused = fe->unused;
memcpy(buf, &unused, sizeof(int));
buf += sizeof(int);
// ncaches
ncaches = eina_list_count(fe->caches);
memcpy(buf, &ncaches, sizeof(int));
buf += sizeof(int);
EINA_LIST_FOREACH(fe->caches, iter, fc)
{
Glyph_Data *gldata;
const char *shmname;
unsigned int shmsize;
unsigned int k;
// shmnamelen + shmname
shmname = cserve2_shm_name_get(fc->shm);
len = strlen(shmname) + 1;
memcpy(buf, &len, sizeof(int));
buf += sizeof(int);
memcpy(buf, shmname, len);
buf += len;
// TODO: Simplify memcpy operations (can be factorized into 1)
// size, usage, nglyphs
shmsize = cserve2_shm_size_get(fc->shm);
memcpy(buf, &shmsize, sizeof(int));
buf += sizeof(int);
memcpy(buf, &fc->usage, sizeof(int));
buf += sizeof(int);
memcpy(buf, &fc->nglyphs, sizeof(int));
buf += sizeof(int);
for (k = 0; k < fc->nglyphs; k++)
{
int *gldata_id = cserve2_shared_array_item_data_get(
fc->glyphs, fc->nglyphs);
gldata = _glyph_data_find(*gldata_id);
// index, shm_id, offset, size
memcpy(buf, &gldata->index, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->shm_id, sizeof(string_t));
buf += sizeof(string_t);
memcpy(buf, &gldata->offset, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->size, sizeof(int));
buf += sizeof(int);
// rows, width, pitch
memcpy(buf, &gldata->rows, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->width, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->pitch, sizeof(int));
buf += sizeof(int);
// num_grays, pixel_mode
memcpy(buf, &gldata->num_grays, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->pixel_mode, sizeof(int));
buf += sizeof(int);
}
}
*pos = buf;
return EINA_TRUE;
#endif
}
static void *
_cserve2_cache_font_debug(unsigned int rid, unsigned int *size)
{
@ -2582,27 +2324,24 @@ _cserve2_cache_font_debug(unsigned int rid, unsigned int *size)
msg.base.type = CSERVE2_FONT_DEBUG;
msg.base.rid = rid;
eina_strlcpy(msg.fonts_index_path,
cserve2_shared_array_name_get(_font_data_array),
sizeof(msg.fonts_index_path));
// First calculate how much size is needed for this message:
// nfonts
di.size += sizeof(unsigned int);
// size needed for each font entry
// First calculate how much size is needed for this message
eina_hash_foreach(font_entries, _font_entry_debug_size_cb, &di);
// Now really create the message
buf = malloc(di.size);
pos = buf;
// nfonts
msg.nfonts = di.nfonts;
// msg base
memcpy(buf, &msg, sizeof(msg));
pos += sizeof(msg);
// nfonts
memcpy(pos, &di.nfonts, sizeof(unsigned int));
pos += sizeof(unsigned int);
eina_hash_foreach(font_entries, _font_entry_debug_cb, &pos);
*size = di.size;
@ -3072,6 +2811,7 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name,
_entry_load_reused(&fe->base);
fe->unused = EINA_FALSE;
_font_lru_update(fe);
if (fe->base.request)
cserve2_request_waiter_add(fe->base.request, rid, client);
@ -3090,6 +2830,7 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name,
ref = _entry_reference_add((Entry *)fe, client, 0);
client->fonts.referencing = eina_list_append(client->fonts.referencing, ref);
fe->unused = EINA_FALSE;
_font_lru_update(fe);
fs = _cserve2_font_source_find(fullname);
if (!fs)
@ -3204,12 +2945,6 @@ cserve2_cache_font_glyphs_used(Client *client, const char *source,
unsigned int nglyphs,
unsigned int rid EINA_UNUSED)
{
// FIXME TODO: Must reimplement this
return 0;
#if 0
Glyphs_Group *gg;
Eina_List *groups;
Glyphs_Request *req;
DBG("Received report of used glyphs from client %d", client->id);
@ -3221,22 +2956,12 @@ cserve2_cache_font_glyphs_used(Client *client, const char *source,
return 0;
}
_glyphs_request_check(req, EINA_FALSE);
groups = _glyphs_group_create(req);
// Promote SHMs which are still cached and in use
// TODO: We can use later the information from request_prepare to preload
// glyphs which are not cached anymore, but are in use on the client.
EINA_LIST_FREE(groups, gg)
{
//_font_shm_promote(gg->fc);
eina_list_free(gg->glyphs);
free(gg);
}
// TODO: We could finetune based on which glyphs exactly are used.
req->fe->unused = EINA_FALSE;
_font_lru_update(req->fe);
_glyphs_request_free(req);
return 0;
#endif
}
void

View File

@ -177,8 +177,6 @@ _debug_msg_send(void)
}
typedef struct _Font_Entry Font_Entry;
typedef struct _Cache_Entry Cache_Entry;
typedef struct _Glyph_Entry Glyph_Entry;
struct _Font_Entry
{
@ -188,27 +186,9 @@ struct _Font_Entry
unsigned int size;
unsigned int dpi;
unsigned int unused;
Eina_List *caches;
};
struct _Cache_Entry
{
const char *shmname;
unsigned int size;
unsigned int usage;
Eina_List *glyphs;
};
struct _Glyph_Entry
{
unsigned int index;
unsigned int offset;
unsigned int size;
unsigned int rows;
unsigned int width;
unsigned int pitch;
unsigned int num_grays;
unsigned int pixel_mode;
char glyph_data_shm[64];
char glyph_mempool_shm[64];
Eina_List *glyphs; // Glyph_Data
};
#define READIT(_dst, _src) \
@ -217,6 +197,7 @@ struct _Glyph_Entry
_src += sizeof(_dst); \
} while(0)
#if 0
static Glyph_Entry *
_parse_glyph_entry(char **msg)
{
@ -267,6 +248,7 @@ _parse_cache_entry(char **msg)
return ce;
}
#endif
static Font_Entry *
_parse_font_entry(char **msg)
@ -291,12 +273,18 @@ _parse_font_entry(char **msg)
READIT(fe->dpi, buf);
READIT(fe->unused, buf);
eina_strlcpy(fe->glyph_data_shm, buf, 64);
buf += 64;
eina_strlcpy(fe->glyph_mempool_shm, buf, 64);
buf += 64;
READIT(n, buf);
while (n--)
{
Cache_Entry *ce;
ce = _parse_cache_entry(&buf);
fe->caches = eina_list_append(fe->caches, ce);
Glyph_Data *gd = calloc(1, sizeof(Glyph_Data));
memcpy(gd, buf, sizeof(Glyph_Data));
buf += sizeof(Glyph_Data);
fe->glyphs = eina_list_append(fe->glyphs, gd);
}
*msg = buf;
@ -307,7 +295,7 @@ _parse_font_entry(char **msg)
static Eina_List *
_debug_msg_read(void)
{
Msg_Base *msg = NULL;
Msg_Font_Debug *msg = NULL;
char *buf;
int size;
unsigned int nfonts;
@ -317,16 +305,16 @@ _debug_msg_read(void)
while (!msg)
msg = _server_read(&size);
if (msg->type != CSERVE2_FONT_DEBUG)
if (msg->base.type != CSERVE2_FONT_DEBUG)
{
ERR("Invalid message received from server."
ERR("Invalid message received from server. "
"Something went badly wrong.");
return NULL;
}
buf = (char *)msg + sizeof(*msg);
READIT(nfonts, buf);
nfonts = msg->nfonts;
while (nfonts--)
{
Font_Entry *fe;
@ -334,34 +322,18 @@ _debug_msg_read(void)
fonts = eina_list_append(fonts, fe);
}
printf("Font index table: %s\n", msg->fonts_index_path);
printf("Contains %u fonts\n\n", msg->nfonts);
return fonts;
}
static void
_glyph_entry_free(Glyph_Entry *ge)
{
free(ge);
}
static void
_cache_entry_free(Cache_Entry *ce)
{
Glyph_Entry *ge;
EINA_LIST_FREE(ce->glyphs, ge)
_glyph_entry_free(ge);
eina_stringshare_del(ce->shmname);
free(ce);
}
static void
_font_entry_free(Font_Entry *fe)
{
Cache_Entry *ce;
Glyph_Data *gd;
EINA_LIST_FREE(fe->caches, ce)
_cache_entry_free(ce);
EINA_LIST_FREE(fe->glyphs, gd)
free(gd);
eina_stringshare_del(fe->name);
eina_stringshare_del(fe->file);
@ -369,7 +341,7 @@ _font_entry_free(Font_Entry *fe)
}
static void
_glyph_entry_print(Glyph_Entry *ge)
_glyph_data_print(Glyph_Data *gd)
{
const char *pxmode[] = {
"FT_PIXEL_MODE_NONE",
@ -380,29 +352,18 @@ _glyph_entry_print(Glyph_Entry *ge)
"FT_PIXEL_MODE_LCD",
"FT_PIXEL_MODE_LCD_V"
};
printf("\t\tGLYPH %u offset: %u size: %u %ux%u pitch: %u grays: %u "
"pixel mode: %s\n",
ge->index, ge->offset, ge->size, ge->width, ge->rows, ge->pitch,
ge->num_grays, pxmode[ge->pixel_mode]);
}
static void
_cache_entry_print(Cache_Entry *ce)
{
Eina_List *l;
Glyph_Entry *ge;
printf("\tSHM %s used %u/%u\n", ce->shmname, ce->usage, ce->size);
EINA_LIST_FOREACH(ce->glyphs, l, ge)
_glyph_entry_print(ge);
printf(" GLYPH id: %-4u refcount %-2u: index: %-6u offset: %-6u size: %-3u "
"%2ux%-3u pitch: %-2u grays: %-3u pixel mode: %s\n",
gd->id, gd->refcount, gd->index, gd->offset, gd->size,
gd->width, gd->rows, gd->pitch,
gd->num_grays, pxmode[gd->pixel_mode]);
}
static void
_font_entry_print(Font_Entry *fe)
{
Eina_List *l;
Cache_Entry *ce;
Glyph_Data *gd;
printf("FONT %s:%s size: %u dpi: %u %s%s%s %s\n",
fe->file, fe->name, fe->size, fe->dpi,
@ -410,18 +371,46 @@ _font_entry_print(Font_Entry *fe)
fe->rend_flags & 1 ? "SLANT " : "",
fe->rend_flags & 2 ? "WEIGHT" : "",
fe->unused ? "(unused)" : "");
printf(" Index: %s\n"
" Mempool: %s\n"
" Glyph count: %u\n",
fe->glyph_data_shm, fe->glyph_mempool_shm,
eina_list_count(fe->glyphs));
EINA_LIST_FOREACH(fe->caches, l, ce)
_cache_entry_print(ce);
EINA_LIST_FOREACH(fe->glyphs, l, gd)
_glyph_data_print(gd);
putchar('\n');
}
static void
_shared_index_print(Msg_Index_List *msg, size_t size)
{
if (size < sizeof(*msg) || msg->base.type != CSERVE2_INDEX_LIST)
{
ERR("Invalid message received from server. "
"Something went wrong.");
return;
}
printf("Printing shared indexes status.\n");
printf("===============================\n\n");
printf("Generation ID: %-4d\n", msg->generation_id);
printf("Strings entries path: %s\n", msg->strings_entries_path);
printf("Strings index path: %s\n", msg->strings_index_path);
printf("Files index path: %s\n", msg->files_index_path);
printf("Images index path: %s\n", msg->images_index_path);
printf("Fonts index path: %s\n", msg->fonts_index_path);
printf("\n\n\n");
}
int
main(void)
{
Eina_List *fonts;
Font_Entry *fe;
Msg_Index_List *msg = NULL;
int size;
eina_init();
_evas_cserve2_debug_log_dom = eina_log_domain_register
@ -431,6 +420,11 @@ main(void)
ERR("Could not connect to server.");
return -1;
}
while (!msg)
msg = _server_read(&size);
_shared_index_print(msg, size);
_debug_msg_send();
fonts = _debug_msg_read();
EINA_LIST_FREE(fonts, fe)

View File

@ -292,6 +292,13 @@ cserve2_shared_array_count_get(Shared_Array *sa)
return sa->header->emptyidx;
}
int
cserve2_shared_array_map_size_get(Shared_Array *sa)
{
if (!sa || !sa->ds) return 0;
return cserve2_shm_map_size_get(sa->ds->shm);
}
int
cserve2_shared_array_item_size_get(Shared_Array *sa)
{
@ -841,7 +848,8 @@ size_t
cserve2_shared_mempool_size_get(Shared_Mempool *sm)
{
if (!sm) return 0;
return cserve2_shm_map_size_get(sm->ds->shm);
return cserve2_shm_map_size_get(sm->ds->shm)
+ cserve2_shared_array_map_size_get(sm->index->sa);
}
const char *

View File

@ -176,48 +176,81 @@ _usage_msg_send(void)
}
}
static void
_shared_index_print(Msg_Base *data, size_t size)
{
Msg_Index_List *msg = (Msg_Index_List *) data;
if (size < sizeof(*msg) || msg->base.type != CSERVE2_INDEX_LIST)
{
ERR("Invalid message received from server. "
"Something went wrong.");
return;
}
printf("Printing shared indexes status.\n");
printf("===============================\n\n");
printf("Generation ID: %-4d\n", msg->generation_id);
printf("Strings entries path: %s\n", msg->strings_entries_path);
printf("Strings index path: %s\n", msg->strings_index_path);
printf("Files index path: %s\n", msg->files_index_path);
printf("Images index path: %s\n", msg->images_index_path);
printf("Fonts index path: %s\n", msg->fonts_index_path);
printf("\n\n\n");
}
static void
_usage_msg_read(void)
{
Msg_Stats *msg = NULL;
Msg_Stats *stats = NULL;
int size;
printf("Requesting server statistics.\n\n");
while (!msg)
msg = _server_read(&size);
if (msg->base.type != CSERVE2_STATS)
while (!stats)
{
ERR("Invalid message received from server."
"Something went badly wrong.");
return;
Msg_Base *msg = _server_read(&size);
if (!msg) continue;
switch (msg->type)
{
case CSERVE2_INDEX_LIST:
_shared_index_print(msg, size);
break;
case CSERVE2_STATS:
stats = (Msg_Stats *) msg;
break;
default:
ERR("Invalid message received from server. "
"Something went badly wrong.");
return;
}
}
printf("Printing server usage.\n");
printf("======================\n\n");
printf("\nImage Usage Statistics:\n");
printf("----------------------\n\n");
printf("Image headers usage: %d bytes\n", msg->images.files_size);
printf("Image data requested: %d kbytes\n", msg->images.requested_size / 1024);
printf("Image data usage: %d kbytes\n", msg->images.images_size / 1024);
printf("Image data unused: %d kbytes\n", msg->images.unused_size / 1024);
printf("Image headers load time: %dus\n", msg->images.files_load_time);
printf("Image headers saved time: %dus\n", msg->images.files_saved_time);
printf("Image data load time: %dus\n", msg->images.images_load_time);
printf("Image data saved time: %dus\n", msg->images.images_saved_time);
printf("Image headers usage: %d bytes\n", stats->images.files_size);
printf("Image data requested: %d kbytes\n", stats->images.requested_size / 1024);
printf("Image data usage: %d kbytes\n", stats->images.images_size / 1024);
printf("Image data unused: %d kbytes\n", stats->images.unused_size / 1024);
printf("Image headers load time: %dus\n", stats->images.files_load_time);
printf("Image headers saved time: %dus\n", stats->images.files_saved_time);
printf("Image data load time: %dus\n", stats->images.images_load_time);
printf("Image data saved time: %dus\n", stats->images.images_saved_time);
printf("\nFont Usage Statistics:\n");
printf("----------------------\n\n");
printf("Requested usage: %d bytes\n", msg->fonts.requested_size);
printf("Real usage: %d bytes\n", msg->fonts.real_size);
printf("Unused size: %d bytes\n", msg->fonts.unused_size);
printf("Fonts load time: %dus\n", msg->fonts.fonts_load_time);
printf("Fonts used load time: %dus\n", msg->fonts.fonts_used_load_time);
printf("Fonts used saved time: %dus\n", msg->fonts.fonts_used_saved_time);
printf("Glyphs load time: %dus\n", msg->fonts.glyphs_load_time);
printf("Glyphs render time: %dus\n", msg->fonts.glyphs_render_time);
printf("Glyphs saved time: %dus\n", msg->fonts.glyphs_saved_time);
printf("Glyphs request time: %dus\n", msg->fonts.glyphs_request_time);
printf("Glyphs slave time: %dus\n", msg->fonts.glyphs_slave_time);
printf("Requested usage: %d bytes\n", stats->fonts.requested_size);
printf("Real usage: %d bytes\n", stats->fonts.real_size);
printf("Unused size: %d bytes\n", stats->fonts.unused_size);
printf("Fonts load time: %dus\n", stats->fonts.fonts_load_time);
printf("Fonts used load time: %dus\n", stats->fonts.fonts_used_load_time);
printf("Fonts used saved time: %dus\n", stats->fonts.fonts_used_saved_time);
printf("Glyphs load time: %dus\n", stats->fonts.glyphs_load_time);
printf("Glyphs render time: %dus\n", stats->fonts.glyphs_render_time);
printf("Glyphs saved time: %dus\n", stats->fonts.glyphs_saved_time);
printf("Glyphs request time: %dus\n", stats->fonts.glyphs_request_time);
printf("Glyphs slave time: %dus\n", stats->fonts.glyphs_slave_time);
printf("\n");
}

View File

@ -231,6 +231,7 @@ struct _Msg_Stats {
*
* Content of the message follows:
*
* * char fonts_index_path[64]
* * number of font entries;
* * each font entry:
* - unsigned int filelen
@ -241,15 +242,15 @@ struct _Msg_Stats {
* - unsigned int size;
* - unsigned int dpi;
* - unsigned int unused;
* - ncaches:
* - each cache:
* * usigned int shmnamelen;
* * const char shmname;
* * unsigned int size;
* * unsigned int usage;
* * unsigned int nglyphs;
* * each glyph:
* - const char glyph_data_shm[64];
* - const char glyph_mempool_shm[64];
* - unsigned int nglyphs;
* - each glyph: Glyph_Data struct
* - unsigned int id;
* - unsigned int refcount;
* - unsigned int index;
* - unsigned int shm_id; // shared string id
* - unsigned int buffer_id;
* - unsigned int offset;
* - unsigned int size;
* - unsigned int rows;
@ -260,6 +261,8 @@ struct _Msg_Stats {
*/
struct _Msg_Font_Debug {
Msg_Base base;
char fonts_index_path[64];
int nfonts;
};
/**