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); void cserve2_shared_array_del(Shared_Array *sa);
int cserve2_shared_array_size_get(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_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_item_size_get(Shared_Array *sa);
int cserve2_shared_array_generation_id_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); 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; 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 static void
_font_entry_free(Font_Entry *fe) _font_entry_free(Font_Entry *fe)
{ {
Font_Data *fd; Font_Data *fd;
int size;
if (!fe) return; 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); fd = _font_data_find(fe->font_data_id);
if (fd) if (fd)
@ -1098,6 +1120,7 @@ _font_entry_free(Font_Entry *fe)
fash_gl_free(fe->glyph_entries); fash_gl_free(fe->glyph_entries);
cserve2_shared_array_del(fe->glyph_datas); cserve2_shared_array_del(fe->glyph_datas);
cserve2_shared_mempool_del(fe->mempool);
cserve2_font_ft_free(fe->ft); cserve2_font_ft_free(fe->ft);
fe->src->refcount--; fe->src->refcount--;
if (fe->src->refcount <= 0) if (fe->src->refcount <= 0)
@ -1141,79 +1164,49 @@ _font_source_free(Font_Source *fs)
free(fs); free(fs);
} }
#if 0
static void static void
_font_shm_promote(Font_Cache *fc) _font_lru_update(Font_Entry *fe)
{ {
Eina_List *l; Eina_List *l;
l = eina_list_data_find_list(font_shm_lru, fc); l = eina_list_data_find_list(font_shm_lru, fe);
font_shm_lru = eina_list_demote_list(font_shm_lru, l); if (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++)
{ {
int *gldata_id = cserve2_shared_array_item_data_get(fc->glyphs, k); if (fe->unused)
gd = _glyph_data_find(*gldata_id); font_shm_lru = eina_list_promote_list(font_shm_lru, l);
fash_gl_del(fe->glyphs, gd->index); else
font_shm_lru = eina_list_demote_list(font_shm_lru, l);
} }
else
cserve2_shared_array_del(fc->glyphs); font_shm_lru = eina_list_append(font_shm_lru, fe);
cserve2_shm_unref(fc->shm);
free(fc);
if (!fe->caches)
eina_hash_del_by_key(font_entries, fe);
} }
static void static void
_font_shm_lru_flush(void) _font_lru_flush(void)
{ {
Eina_List *l, *l_next; Eina_List *l, *l_next;
l = font_shm_lru; l = font_shm_lru;
l_next = eina_list_next(l); 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) while (l && font_mem_usage > max_font_usage)
{ {
int size; Font_Entry *fe;
Font_Cache *fc;
fc = eina_list_data_get(l); fe = eina_list_data_get(l);
if (fc->fe->unused && fc->inuse == 0) if (fe->unused)
{ {
font_shm_lru = eina_list_remove_list(font_shm_lru, l); font_shm_lru = eina_list_remove_list(font_shm_lru, l);
size = _font_shm_size_get(fc); eina_hash_del_by_key(font_entries, fe);
size += fc->nglyphs * sizeof(Glyph_Entry);
_font_shm_free(fc);
font_mem_usage -= size;
} }
l = l_next; l = l_next;
l_next = eina_list_next(l); l_next = eina_list_next(l);
} }
DBG("Font memory usage [end]: %d / %d", font_mem_usage, max_font_usage);
} }
#endif
void void
cserve2_cache_init(void) cserve2_cache_init(void)
@ -1352,10 +1345,10 @@ _entry_reference_del(Entry *entry, Reference *ref)
} }
else if (entry->type == CSERVE2_FONT_ENTRY) else if (entry->type == CSERVE2_FONT_ENTRY)
{ {
Font_Entry *fe = (Font_Entry *)entry; Font_Entry *fe = (Font_Entry *) entry;
fe->unused = EINA_TRUE; fe->unused = EINA_TRUE;
if (!fe->mempool) _font_lru_update(fe);
eina_hash_del_by_key(font_entries, fe); _font_lru_flush();
} }
else else
ERR("Wrong type of entry."); ERR("Wrong type of entry.");
@ -1719,150 +1712,6 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
return (req->nanswer == req->nglyphs); 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 * static Msg_Font_Glyphs_Loaded *
_glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size) _glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
{ {
@ -2105,11 +1954,19 @@ _glyphs_load_request_response(Glyphs_Request *req,
if (!msg->nglyphs) if (!msg->nglyphs)
return _glyphs_loaded_msg_create(req, size); return _glyphs_loaded_msg_create(req, size);
DBG("Font memory usage [begin]: %d / %d", font_mem_usage, max_font_usage);
if (!mempool) 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) 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)); shm_id = cserve2_shared_string_add(cserve2_shared_mempool_name_get(mempool));
for (j = 0; j < msg->nglyphs; j++) 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); gl = fash_gl_find(fe->glyph_entries, msg->glyphs[j].index);
if (!gl) if (!gl)
{ {
int glyph_id; int glyph_id, orig_mapsize, new_mapsize;
Glyph_Data *gldata; Glyph_Data *gldata;
orig_mapsize = cserve2_shared_array_map_size_get(fe->glyph_datas);
glyph_id = cserve2_shared_array_item_new(fe->glyph_datas); glyph_id = cserve2_shared_array_item_new(fe->glyph_datas);
gldata = cserve2_shared_array_item_data_get(fe->glyph_datas, gldata = cserve2_shared_array_item_data_get(fe->glyph_datas,
glyph_id); glyph_id);
@ -2152,7 +2011,9 @@ _glyphs_load_request_response(Glyphs_Request *req,
fe->nglyphs++; fe->nglyphs++;
fash_gl_add(fe->glyph_entries, gldata->index, gl); 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; req->answer[req->nanswer++] = gl;
} }
@ -2169,6 +2030,9 @@ _glyphs_load_request_response(Glyphs_Request *req,
fe->mempool = mempool; 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); return _glyphs_loaded_msg_create(req, size);
} }
@ -2185,42 +2049,39 @@ static Slave_Request_Funcs _glyphs_load_funcs = {
}; };
static Eina_Bool 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; Font_Entry *fe = data;
Msg_Stats *msg = fdata; Msg_Stats *msg = fdata;
Eina_List *iter; unsigned int shmsize;
Font_Cache *fc;
int nrefs = eina_list_count(fe->base.references);
msg->fonts.fonts_loaded++; msg->fonts.fonts_loaded++;
if (fe->unused) msg->fonts.fonts_unused++; if (fe->unused) msg->fonts.fonts_unused++;
// accounting size // accounting size
EINA_LIST_FOREACH(fe->caches, iter, fc) shmsize = cserve2_shared_mempool_size_get(fe->mempool);
{ msg->fonts.real_size += shmsize;
unsigned int fc_usage, shmsize; if (fe->unused) msg->fonts.unused_size += 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);
msg->fonts.requested_size += fc_usage; cserve2_shared_array_foreach(fe->glyph_datas,
msg->fonts.real_size += shmsize; EINA_EACH_CB(_font_requested_size_cb), msg);
if (fe->unused) msg->fonts.unused_size += shmsize;
}
#ifdef DEBUG_LOAD_TIME #ifdef DEBUG_LOAD_TIME
// accounting fonts load time // accounting fonts load time
msg->fonts.fonts_load_time += fe->base.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_load_time += fe->base.load_time;
msg->fonts.fonts_used_saved_time += fe->base.saved_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_saved_time += fe->gl_saved_time;
msg->fonts.glyphs_request_time += fe->gl_request_time; msg->fonts.glyphs_request_time += fe->gl_request_time;
msg->fonts.glyphs_slave_time += fe->gl_slave_time; msg->fonts.glyphs_slave_time += fe->gl_slave_time;
#endif
#endif #endif
return EINA_TRUE; return EINA_TRUE;
@ -2319,52 +2178,53 @@ struct _debug_info
}; };
static Eina_Bool 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; struct _debug_info *di = fdata;
unsigned int size = di->size;
Font_Entry *fe = data; Font_Entry *fe = data;
const char *str; const char *str;
// filelen // filelen
size += sizeof(int); di->size+= sizeof(int);
// file // file
if (fe->src->file) if (fe->src->file)
{ {
str = cserve2_shared_string_get(fe->src->file); str = cserve2_shared_string_get(fe->src->file);
size += strlen(str) + 1; di->size+= strlen(str) + 1;
} }
// namelen // namelen
size += sizeof(int); di->size+= sizeof(int);
// name // name
if (fe->src->name) if (fe->src->name)
{ {
str = cserve2_shared_string_get(fe->src->file); str = cserve2_shared_string_get(fe->src->file);
size += strlen(str) + 1; di->size+= strlen(str) + 1;
} }
// rend_flags, size, dpi // rend_flags, size, dpi, unused
size += 3 * sizeof(int); di->size+= 4 * sizeof(int);
// unused // glyph_data_shm and glyph_mempool_shm (short strings)
size += sizeof(int); di->size+= 2 * 64;
// ncaches // nglyphs
size += sizeof(int); 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++; di->nfonts++;
return EINA_TRUE; return EINA_TRUE;
} }
static Eina_Bool 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 **pos = fdata;
char *buf = *pos; 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; 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 * static void *
_cserve2_cache_font_debug(unsigned int rid, unsigned int *size) _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.type = CSERVE2_FONT_DEBUG;
msg.base.rid = rid; 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: // First calculate how much size is needed for this message
// nfonts
di.size += sizeof(unsigned int);
// size needed for each font entry
eina_hash_foreach(font_entries, _font_entry_debug_size_cb, &di); eina_hash_foreach(font_entries, _font_entry_debug_size_cb, &di);
// Now really create the message // Now really create the message
buf = malloc(di.size); buf = malloc(di.size);
pos = buf; pos = buf;
// nfonts
msg.nfonts = di.nfonts;
// msg base // msg base
memcpy(buf, &msg, sizeof(msg)); memcpy(buf, &msg, sizeof(msg));
pos += 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); eina_hash_foreach(font_entries, _font_entry_debug_cb, &pos);
*size = di.size; *size = di.size;
@ -3072,6 +2811,7 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name,
_entry_load_reused(&fe->base); _entry_load_reused(&fe->base);
fe->unused = EINA_FALSE; fe->unused = EINA_FALSE;
_font_lru_update(fe);
if (fe->base.request) if (fe->base.request)
cserve2_request_waiter_add(fe->base.request, rid, client); 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); ref = _entry_reference_add((Entry *)fe, client, 0);
client->fonts.referencing = eina_list_append(client->fonts.referencing, ref); client->fonts.referencing = eina_list_append(client->fonts.referencing, ref);
fe->unused = EINA_FALSE; fe->unused = EINA_FALSE;
_font_lru_update(fe);
fs = _cserve2_font_source_find(fullname); fs = _cserve2_font_source_find(fullname);
if (!fs) if (!fs)
@ -3204,12 +2945,6 @@ cserve2_cache_font_glyphs_used(Client *client, const char *source,
unsigned int nglyphs, unsigned int nglyphs,
unsigned int rid EINA_UNUSED) unsigned int rid EINA_UNUSED)
{ {
// FIXME TODO: Must reimplement this
return 0;
#if 0
Glyphs_Group *gg;
Eina_List *groups;
Glyphs_Request *req; Glyphs_Request *req;
DBG("Received report of used glyphs from client %d", client->id); 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; return 0;
} }
_glyphs_request_check(req, EINA_FALSE); // TODO: We could finetune based on which glyphs exactly are used.
groups = _glyphs_group_create(req); req->fe->unused = EINA_FALSE;
_font_lru_update(req->fe);
// 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);
}
_glyphs_request_free(req); _glyphs_request_free(req);
return 0; return 0;
#endif
} }
void void

View File

@ -177,8 +177,6 @@ _debug_msg_send(void)
} }
typedef struct _Font_Entry Font_Entry; typedef struct _Font_Entry Font_Entry;
typedef struct _Cache_Entry Cache_Entry;
typedef struct _Glyph_Entry Glyph_Entry;
struct _Font_Entry struct _Font_Entry
{ {
@ -188,27 +186,9 @@ struct _Font_Entry
unsigned int size; unsigned int size;
unsigned int dpi; unsigned int dpi;
unsigned int unused; unsigned int unused;
Eina_List *caches; char glyph_data_shm[64];
}; char glyph_mempool_shm[64];
Eina_List *glyphs; // Glyph_Data
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;
}; };
#define READIT(_dst, _src) \ #define READIT(_dst, _src) \
@ -217,6 +197,7 @@ struct _Glyph_Entry
_src += sizeof(_dst); \ _src += sizeof(_dst); \
} while(0) } while(0)
#if 0
static Glyph_Entry * static Glyph_Entry *
_parse_glyph_entry(char **msg) _parse_glyph_entry(char **msg)
{ {
@ -267,6 +248,7 @@ _parse_cache_entry(char **msg)
return ce; return ce;
} }
#endif
static Font_Entry * static Font_Entry *
_parse_font_entry(char **msg) _parse_font_entry(char **msg)
@ -291,12 +273,18 @@ _parse_font_entry(char **msg)
READIT(fe->dpi, buf); READIT(fe->dpi, buf);
READIT(fe->unused, 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); READIT(n, buf);
while (n--) while (n--)
{ {
Cache_Entry *ce; Glyph_Data *gd = calloc(1, sizeof(Glyph_Data));
ce = _parse_cache_entry(&buf); memcpy(gd, buf, sizeof(Glyph_Data));
fe->caches = eina_list_append(fe->caches, ce); buf += sizeof(Glyph_Data);
fe->glyphs = eina_list_append(fe->glyphs, gd);
} }
*msg = buf; *msg = buf;
@ -307,7 +295,7 @@ _parse_font_entry(char **msg)
static Eina_List * static Eina_List *
_debug_msg_read(void) _debug_msg_read(void)
{ {
Msg_Base *msg = NULL; Msg_Font_Debug *msg = NULL;
char *buf; char *buf;
int size; int size;
unsigned int nfonts; unsigned int nfonts;
@ -317,16 +305,16 @@ _debug_msg_read(void)
while (!msg) while (!msg)
msg = _server_read(&size); 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."); "Something went badly wrong.");
return NULL; return NULL;
} }
buf = (char *)msg + sizeof(*msg); buf = (char *)msg + sizeof(*msg);
READIT(nfonts, buf); nfonts = msg->nfonts;
while (nfonts--) while (nfonts--)
{ {
Font_Entry *fe; Font_Entry *fe;
@ -334,34 +322,18 @@ _debug_msg_read(void)
fonts = eina_list_append(fonts, fe); 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; 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 static void
_font_entry_free(Font_Entry *fe) _font_entry_free(Font_Entry *fe)
{ {
Cache_Entry *ce; Glyph_Data *gd;
EINA_LIST_FREE(fe->caches, ce) EINA_LIST_FREE(fe->glyphs, gd)
_cache_entry_free(ce); free(gd);
eina_stringshare_del(fe->name); eina_stringshare_del(fe->name);
eina_stringshare_del(fe->file); eina_stringshare_del(fe->file);
@ -369,7 +341,7 @@ _font_entry_free(Font_Entry *fe)
} }
static void static void
_glyph_entry_print(Glyph_Entry *ge) _glyph_data_print(Glyph_Data *gd)
{ {
const char *pxmode[] = { const char *pxmode[] = {
"FT_PIXEL_MODE_NONE", "FT_PIXEL_MODE_NONE",
@ -380,29 +352,18 @@ _glyph_entry_print(Glyph_Entry *ge)
"FT_PIXEL_MODE_LCD", "FT_PIXEL_MODE_LCD",
"FT_PIXEL_MODE_LCD_V" "FT_PIXEL_MODE_LCD_V"
}; };
printf("\t\tGLYPH %u offset: %u size: %u %ux%u pitch: %u grays: %u " printf(" GLYPH id: %-4u refcount %-2u: index: %-6u offset: %-6u size: %-3u "
"pixel mode: %s\n", "%2ux%-3u pitch: %-2u grays: %-3u pixel mode: %s\n",
ge->index, ge->offset, ge->size, ge->width, ge->rows, ge->pitch, gd->id, gd->refcount, gd->index, gd->offset, gd->size,
ge->num_grays, pxmode[ge->pixel_mode]); gd->width, gd->rows, gd->pitch,
} gd->num_grays, pxmode[gd->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);
} }
static void static void
_font_entry_print(Font_Entry *fe) _font_entry_print(Font_Entry *fe)
{ {
Eina_List *l; Eina_List *l;
Cache_Entry *ce; Glyph_Data *gd;
printf("FONT %s:%s size: %u dpi: %u %s%s%s %s\n", printf("FONT %s:%s size: %u dpi: %u %s%s%s %s\n",
fe->file, fe->name, fe->size, fe->dpi, 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 & 1 ? "SLANT " : "",
fe->rend_flags & 2 ? "WEIGHT" : "", fe->rend_flags & 2 ? "WEIGHT" : "",
fe->unused ? "(unused)" : ""); 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) EINA_LIST_FOREACH(fe->glyphs, l, gd)
_cache_entry_print(ce); _glyph_data_print(gd);
putchar('\n'); 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 int
main(void) main(void)
{ {
Eina_List *fonts; Eina_List *fonts;
Font_Entry *fe; Font_Entry *fe;
Msg_Index_List *msg = NULL;
int size;
eina_init(); eina_init();
_evas_cserve2_debug_log_dom = eina_log_domain_register _evas_cserve2_debug_log_dom = eina_log_domain_register
@ -431,6 +420,11 @@ main(void)
ERR("Could not connect to server."); ERR("Could not connect to server.");
return -1; return -1;
} }
while (!msg)
msg = _server_read(&size);
_shared_index_print(msg, size);
_debug_msg_send(); _debug_msg_send();
fonts = _debug_msg_read(); fonts = _debug_msg_read();
EINA_LIST_FREE(fonts, fe) EINA_LIST_FREE(fonts, fe)

View File

@ -292,6 +292,13 @@ cserve2_shared_array_count_get(Shared_Array *sa)
return sa->header->emptyidx; 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 int
cserve2_shared_array_item_size_get(Shared_Array *sa) cserve2_shared_array_item_size_get(Shared_Array *sa)
{ {
@ -841,7 +848,8 @@ size_t
cserve2_shared_mempool_size_get(Shared_Mempool *sm) cserve2_shared_mempool_size_get(Shared_Mempool *sm)
{ {
if (!sm) return 0; 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 * 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 static void
_usage_msg_read(void) _usage_msg_read(void)
{ {
Msg_Stats *msg = NULL; Msg_Stats *stats = NULL;
int size; int size;
printf("Requesting server statistics.\n\n"); 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." Msg_Base *msg = _server_read(&size);
"Something went badly wrong."); if (!msg) continue;
return; 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("Printing server usage.\n");
printf("======================\n\n"); printf("======================\n\n");
printf("\nImage Usage Statistics:\n"); printf("\nImage Usage Statistics:\n");
printf("----------------------\n\n"); printf("----------------------\n\n");
printf("Image headers usage: %d bytes\n", msg->images.files_size); printf("Image headers usage: %d bytes\n", stats->images.files_size);
printf("Image data requested: %d kbytes\n", msg->images.requested_size / 1024); printf("Image data requested: %d kbytes\n", stats->images.requested_size / 1024);
printf("Image data usage: %d kbytes\n", msg->images.images_size / 1024); printf("Image data usage: %d kbytes\n", stats->images.images_size / 1024);
printf("Image data unused: %d kbytes\n", msg->images.unused_size / 1024); printf("Image data unused: %d kbytes\n", stats->images.unused_size / 1024);
printf("Image headers load time: %dus\n", msg->images.files_load_time); printf("Image headers load time: %dus\n", stats->images.files_load_time);
printf("Image headers saved time: %dus\n", msg->images.files_saved_time); printf("Image headers saved time: %dus\n", stats->images.files_saved_time);
printf("Image data load time: %dus\n", msg->images.images_load_time); printf("Image data load time: %dus\n", stats->images.images_load_time);
printf("Image data saved time: %dus\n", msg->images.images_saved_time); printf("Image data saved time: %dus\n", stats->images.images_saved_time);
printf("\nFont Usage Statistics:\n"); printf("\nFont Usage Statistics:\n");
printf("----------------------\n\n"); printf("----------------------\n\n");
printf("Requested usage: %d bytes\n", msg->fonts.requested_size); printf("Requested usage: %d bytes\n", stats->fonts.requested_size);
printf("Real usage: %d bytes\n", msg->fonts.real_size); printf("Real usage: %d bytes\n", stats->fonts.real_size);
printf("Unused size: %d bytes\n", msg->fonts.unused_size); printf("Unused size: %d bytes\n", stats->fonts.unused_size);
printf("Fonts load time: %dus\n", msg->fonts.fonts_load_time); printf("Fonts load time: %dus\n", stats->fonts.fonts_load_time);
printf("Fonts used load time: %dus\n", msg->fonts.fonts_used_load_time); printf("Fonts used load time: %dus\n", stats->fonts.fonts_used_load_time);
printf("Fonts used saved time: %dus\n", msg->fonts.fonts_used_saved_time); printf("Fonts used saved time: %dus\n", stats->fonts.fonts_used_saved_time);
printf("Glyphs load time: %dus\n", msg->fonts.glyphs_load_time); printf("Glyphs load time: %dus\n", stats->fonts.glyphs_load_time);
printf("Glyphs render time: %dus\n", msg->fonts.glyphs_render_time); printf("Glyphs render time: %dus\n", stats->fonts.glyphs_render_time);
printf("Glyphs saved time: %dus\n", msg->fonts.glyphs_saved_time); printf("Glyphs saved time: %dus\n", stats->fonts.glyphs_saved_time);
printf("Glyphs request time: %dus\n", msg->fonts.glyphs_request_time); printf("Glyphs request time: %dus\n", stats->fonts.glyphs_request_time);
printf("Glyphs slave time: %dus\n", msg->fonts.glyphs_slave_time); printf("Glyphs slave time: %dus\n", stats->fonts.glyphs_slave_time);
printf("\n"); printf("\n");
} }

View File

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