eet dict+ data read - move rw lock to ourside decode for speed read

on read/decode we can avoid lots of little locks and unlocked by
having the rwlock go to the outside and a single lock+unlock (read) on
the dictionary. it blocks for longer by has less atomics/fence points
as a result and thus decodes faster where changes that we are writing
while decoding is insanely low so no point worrying here.
This commit is contained in:
Carsten Haitzler 2019-08-10 12:16:58 +01:00
parent 8531380de0
commit 61be4f02bf
3 changed files with 168 additions and 55 deletions

View File

@ -227,16 +227,32 @@ Eet_Dictionary *
eet_dictionary_add(void);
void
eet_dictionary_free(Eet_Dictionary *ed);
void
eet_dictionary_lock_read(const Eet_Dictionary *ed);
void
eet_dictionary_lock_write(Eet_Dictionary *ed);
void
eet_dictionary_unlock(const Eet_Dictionary *ed);
int
eet_dictionary_string_add(Eet_Dictionary *ed,
const char *string);
int
eet_dictionary_string_get_size_unlocked(const Eet_Dictionary *ed,
int index);
int
eet_dictionary_string_get_size(const Eet_Dictionary *ed,
int index);
const char *
eet_dictionary_string_get_char_unlocked(const Eet_Dictionary *ed,
int index);
const char *
eet_dictionary_string_get_char(const Eet_Dictionary *ed,
int index);
Eina_Bool
eet_dictionary_string_get_float_unlocked(const Eet_Dictionary *ed,
int index,
float *result);
Eina_Bool
eet_dictionary_string_get_float(const Eet_Dictionary *ed,
int index,
float *result);
@ -245,9 +261,20 @@ eet_dictionary_string_get_double(const Eet_Dictionary *ed,
int index,
double *result);
Eina_Bool
eet_dictionary_string_get_double_unlocked(const Eet_Dictionary *ed,
int index,
double *result);
Eina_Bool
eet_dictionary_string_get_fp(const Eet_Dictionary *ed,
int index,
Eina_F32p32 *result);
Eina_Bool
eet_dictionary_string_get_fp_unlocked(const Eet_Dictionary *ed,
int index,
Eina_F32p32 *result);
int
eet_dictionary_string_get_hash_unlocked(const Eet_Dictionary *ed,
int index);
int
eet_dictionary_string_get_hash(const Eet_Dictionary *ed,
int index);

View File

@ -786,7 +786,7 @@ eet_data_get_string_hash(const Eet_Dictionary *ed,
if (eet_data_get_int(ed, src, src_end, &idx) < 0)
return -1;
return eet_dictionary_string_get_hash(ed, idx);
return eet_dictionary_string_get_hash_unlocked(ed, idx);
}
return -1;
@ -810,12 +810,12 @@ eet_data_get_string(const Eet_Dictionary *ed,
if (eet_data_get_int(ed, src, src_end, &idx) < 0)
return -1;
str = eet_dictionary_string_get_char(ed, idx);
str = eet_dictionary_string_get_char_unlocked(ed, idx);
if (!str)
return -1;
*d = (char *)str;
return eet_dictionary_string_get_size(ed, idx);
return eet_dictionary_string_get_size_unlocked(ed, idx);
}
s = (char *)src;
@ -996,7 +996,7 @@ eet_data_get_float(const Eet_Dictionary *ed,
if (eet_data_get_int(ed, src, src_end, &idx) < 0)
return -1;
if (!eet_dictionary_string_get_float(ed, idx, d))
if (!eet_dictionary_string_get_float_unlocked(ed, idx, d))
return -1;
return 1;
@ -1073,7 +1073,7 @@ eet_data_get_double(const Eet_Dictionary *ed,
if (eet_data_get_int(ed, src, src_end, &idx) < 0)
return -1;
if (!eet_dictionary_string_get_double(ed, idx, d))
if (!eet_dictionary_string_get_double_unlocked(ed, idx, d))
return -1;
return 1;
@ -1143,7 +1143,7 @@ eet_data_get_f32p32(const Eet_Dictionary *ed,
if (eet_data_get_int(ed, src, src_end, &idx) < 0)
return -1;
if (!eet_dictionary_string_get_fp(ed, idx, fp))
if (!eet_dictionary_string_get_fp_unlocked(ed, idx, fp))
return -1;
return 1;
@ -2283,9 +2283,11 @@ eet_data_read_cipher(Eet_File *ef,
return NULL;
}
eet_dictionary_lock_read(ed); // XXX: get manual eet_dictionary lock
eet_free_context_init(&context);
data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size, NULL, 0);
eet_free_context_shutdown(&context);
eet_dictionary_unlock(ed); // XXX: release manual eet_dictionary lock
if (required_free)
free((void *)data);
@ -2322,9 +2324,11 @@ eet_data_read_cipher_buffer(Eet_File *ef,
return NULL;
}
eet_dictionary_lock_read(ed); // XXX: get manual eet_dictionary lock
eet_free_context_init(&context);
data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size, buffer, buffer_size);
eet_free_context_shutdown(&context);
eet_dictionary_unlock(ed); // XXX: release manual eet_dictionary lock
if (required_free)
free((void *)data);
@ -2357,9 +2361,11 @@ eet_data_node_read_cipher(Eet_File *ef,
return NULL;
}
eet_dictionary_lock_read(ed); // XXX: get manual eet_dictionary lock
eet_free_context_init(&context);
result = _eet_data_descriptor_decode(&context, ed, NULL, data, size, NULL, 0);
eet_free_context_shutdown(&context);
eet_dictionary_unlock(ed); // XXX: release manual eet_dictionary lock
if (required_free)
free((void *)data);
@ -2393,7 +2399,9 @@ eet_data_write_cipher(Eet_File *ef,
ed = eet_dictionary_get(ef);
// XXX: future manual lock?
data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
// XXX: release manual eet_dictionary lock
if (!data_enc)
return 0;
@ -4831,9 +4839,11 @@ eet_data_dump_cipher(Eet_File *ef,
return 0;
}
eet_dictionary_lock_read(ed); // XXX: get manual eet_dictionary lock
eet_free_context_init(&context);
result = _eet_data_descriptor_decode(&context, ed, NULL, data, size, NULL, 0);
eet_free_context_shutdown(&context);
eet_dictionary_unlock(ed); // XXX: release manual eet_dictionary lock
eet_node_dump(result, 0, dumpfunc, dumpdata);
@ -4964,7 +4974,9 @@ eet_data_undump_cipher(Eet_File *ef,
ed = eet_dictionary_get(ef);
// XXX: in future put lock outside here - rare to dump
data_enc = _eet_data_dump_parse(ed, &size, text, textlen);
// XXX: release manual eet_dictionary lock
if (!data_enc)
return 0;
@ -5140,7 +5152,9 @@ eet_data_node_write_cipher(Eet_File *ef,
ed = eet_dictionary_get(ef);
// XXX: in future put lock outside here?
data_enc = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node, &size);
// XXX: release manual eet_dictionary lock
if (!data_enc)
return 0;

View File

@ -72,6 +72,24 @@ _eet_dictionary_lookup(Eet_Dictionary *ed,
return current;
}
void
eet_dictionary_lock_read(const Eet_Dictionary *ed)
{
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
}
void
eet_dictionary_lock_write(Eet_Dictionary *ed)
{
eina_rwlock_take_write((Eina_RWLock *)&ed->rwlock);
}
void
eet_dictionary_unlock(const Eet_Dictionary *ed)
{
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
}
int
eet_dictionary_string_add(Eet_Dictionary *ed,
const char *string)
@ -143,21 +161,31 @@ on_error:
}
int
eet_dictionary_string_get_size(const Eet_Dictionary *ed,
int idx)
eet_dictionary_string_get_size_unlocked(const Eet_Dictionary *ed,
int idx)
{
int length = 0;
if (!ed) goto done;
if (idx < 0) goto done;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (idx < ed->count) length = ed->all[idx].len;
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
done:
return length;
}
int
eet_dictionary_string_get_size(const Eet_Dictionary *ed,
int idx)
{
int length;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
length = eet_dictionary_string_get_size_unlocked(ed, idx);
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return length;
}
EAPI int
eet_dictionary_count(const Eet_Dictionary *ed)
{
@ -172,31 +200,40 @@ eet_dictionary_count(const Eet_Dictionary *ed)
}
int
eet_dictionary_string_get_hash(const Eet_Dictionary *ed,
int idx)
eet_dictionary_string_get_hash_unlocked(const Eet_Dictionary *ed,
int idx)
{
int hash = -1;
if (!ed) goto done;
if (idx < 0) goto done;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (idx < ed->count) hash = ed->all_hash[idx];
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
done:
return hash;
}
const char *
eet_dictionary_string_get_char(const Eet_Dictionary *ed,
int
eet_dictionary_string_get_hash(const Eet_Dictionary *ed,
int idx)
{
int hash;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
hash = eet_dictionary_string_get_hash_unlocked(ed, idx);
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return hash;
}
const char *
eet_dictionary_string_get_char_unlocked(const Eet_Dictionary *ed,
int idx)
{
const char *s = NULL;
if (!ed) goto done;
if (idx < 0) goto done;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (idx < ed->count)
{
#ifdef _WIN32
@ -209,11 +246,22 @@ eet_dictionary_string_get_char(const Eet_Dictionary *ed,
#endif /* ifdef _WIN32 */
s = ed->all[idx].str;
}
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
done:
return s;
}
const char *
eet_dictionary_string_get_char(const Eet_Dictionary *ed,
int idx)
{
const char *s = NULL;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
s = eet_dictionary_string_get_char_unlocked(ed, idx);
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return s;
}
static inline Eina_Bool
_eet_dictionary_string_get_me_cache(const char *s,
int len,
@ -262,9 +310,9 @@ _eet_dictionary_string_get_double_cache(const char *s,
}
static inline Eina_Bool
_eet_dictionary_test(const Eet_Dictionary *ed,
int idx,
void *result)
_eet_dictionary_test_unlocked(const Eet_Dictionary *ed,
int idx,
void *result)
{
Eina_Bool limit = EINA_FALSE;
@ -272,23 +320,19 @@ _eet_dictionary_test(const Eet_Dictionary *ed,
if (!ed) goto done;
if (idx < 0) goto done;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (!(idx < ed->count)) goto unlock_done;
if (!(idx < ed->count)) goto done;
limit = EINA_TRUE;
unlock_done:
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
done:
return limit;
}
static Eet_Convert *
eet_dictionary_convert_get(const Eet_Dictionary *ed,
int idx,
const char **str)
eet_dictionary_convert_get_unlocked(const Eet_Dictionary *ed,
int idx,
const char **str)
{
Eet_Convert *result;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
*str = ed->all[idx].str;
if (!ed->converts)
@ -304,26 +348,24 @@ add_convert:
result = calloc(1, sizeof (Eet_Convert));
eina_hash_add(ed->converts, &idx, result);
done:
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return result;
}
Eina_Bool
eet_dictionary_string_get_float(const Eet_Dictionary *ed,
int idx,
float *result)
eet_dictionary_string_get_float_unlocked(const Eet_Dictionary *ed,
int idx,
float *result)
{
Eet_Convert *convert;
const char *str;
if (!_eet_dictionary_test(ed, idx, result)) return EINA_FALSE;
if (!_eet_dictionary_test_unlocked(ed, idx, result)) return EINA_FALSE;
convert = eet_dictionary_convert_get(ed, idx, &str);
convert = eet_dictionary_convert_get_unlocked(ed, idx, &str);
if (!convert) return EINA_FALSE;
if (!(convert->type & EET_D_FLOAT))
{
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (!_eet_dictionary_string_get_float_cache(str, ed->all[idx].len,
&convert->f))
{
@ -333,12 +375,10 @@ eet_dictionary_string_get_float(const Eet_Dictionary *ed,
if (eina_convert_atod(str, ed->all[idx].len, &mantisse,
&exponent) == EINA_FALSE)
{
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return EINA_FALSE;
}
convert->f = ldexpf((float)mantisse, exponent);
}
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
convert->type |= EET_D_FLOAT;
}
*result = convert->f;
@ -346,22 +386,33 @@ eet_dictionary_string_get_float(const Eet_Dictionary *ed,
}
Eina_Bool
eet_dictionary_string_get_double(const Eet_Dictionary *ed,
int idx,
double *result)
eet_dictionary_string_get_float(const Eet_Dictionary *ed,
int idx,
float *result)
{
Eina_Bool ret;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
ret = eet_dictionary_string_get_float_unlocked(ed, idx, result);
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return ret;
}
Eina_Bool
eet_dictionary_string_get_double_unlocked(const Eet_Dictionary *ed,
int idx,
double *result)
{
Eet_Convert *convert;
const char *str;
if (!_eet_dictionary_test(ed, idx, result)) return EINA_FALSE;
if (!_eet_dictionary_test_unlocked(ed, idx, result)) return EINA_FALSE;
convert = eet_dictionary_convert_get(ed, idx, &str);
convert = eet_dictionary_convert_get_unlocked(ed, idx, &str);
if (!convert) return EINA_FALSE;
if (!(convert->type & EET_D_DOUBLE))
{
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (!_eet_dictionary_string_get_double_cache(str, ed->all[idx].len,
&convert->d))
{
@ -371,12 +422,10 @@ eet_dictionary_string_get_double(const Eet_Dictionary *ed,
if (eina_convert_atod(str, ed->all[idx].len, &mantisse,
&exponent) == EINA_FALSE)
{
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return EINA_FALSE;
}
convert->d = ldexp((double)mantisse, exponent);
}
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
convert->type |= EET_D_DOUBLE;
}
@ -385,29 +434,39 @@ eet_dictionary_string_get_double(const Eet_Dictionary *ed,
}
Eina_Bool
eet_dictionary_string_get_fp(const Eet_Dictionary *ed,
int idx,
Eina_F32p32 *result)
eet_dictionary_string_get_double(const Eet_Dictionary *ed,
int idx,
double *result)
{
Eina_Bool ret;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
ret = eet_dictionary_string_get_double_unlocked(ed, idx, result);
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return ret;
}
Eina_Bool
eet_dictionary_string_get_fp_unlocked(const Eet_Dictionary *ed,
int idx,
Eina_F32p32 *result)
{
Eet_Convert *convert;
const char *str;
if (!_eet_dictionary_test(ed, idx, result)) return EINA_FALSE;
if (!_eet_dictionary_test_unlocked(ed, idx, result)) return EINA_FALSE;
convert = eet_dictionary_convert_get(ed, idx, &str);
convert = eet_dictionary_convert_get_unlocked(ed, idx, &str);
if (!convert) return EINA_FALSE;
if (!(convert->type & EET_D_FIXED_POINT))
{
Eina_F32p32 fp;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
if (!eina_convert_atofp(str, ed->all[idx].len, &fp))
{
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return EINA_FALSE;
}
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
convert->fp = fp;
convert->type |= EET_D_FIXED_POINT;
@ -417,6 +476,19 @@ eet_dictionary_string_get_fp(const Eet_Dictionary *ed,
return EINA_TRUE;
}
Eina_Bool
eet_dictionary_string_get_fp(const Eet_Dictionary *ed,
int idx,
Eina_F32p32 *result)
{
Eina_Bool ret;
eina_rwlock_take_read((Eina_RWLock *)&ed->rwlock);
ret = eet_dictionary_string_get_fp_unlocked(ed, idx, result);
eina_rwlock_release((Eina_RWLock *)&ed->rwlock);
return ret;
}
EAPI int
eet_dictionary_string_check(Eet_Dictionary *ed,
const char *string)