summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Schmidt <s.schmidt@samsung.com>2020-06-17 13:21:24 +0200
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2020-07-06 17:14:36 +0200
commitcac95313c7fd6aad71d48f49efe26d974b0bd5bc (patch)
tree9e1389c82bdba9145003e4f4a9b333fcbb5ea69c
parent972cd7f62bbfaa03d3b25ea1e8ba643de24cf7b9 (diff)
benchmark: eina: remove outdated ecore_hash
Ecore_hash is an ancestor of eina_hash and not used anywhere anymore. We simply forgot to remove it from our benchmark utility. Together with ecore_hash we are removing ecore_strings, which uses it, and the corresponding benchmark files. Signed-off-by: Stefan Schmidt <s.schmidt@samsung.com> Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de> Differential Revision: https://phab.enlightenment.org/D12042
-rw-r--r--po/POTFILES.in4
-rw-r--r--src/benchmarks/eina/Ecore_Data.h75
-rw-r--r--src/benchmarks/eina/ecore_hash.c952
-rw-r--r--src/benchmarks/eina/ecore_strings.c164
-rw-r--r--src/benchmarks/eina/eina_bench.c3
-rw-r--r--src/benchmarks/eina/eina_bench.h3
-rw-r--r--src/benchmarks/eina/eina_bench_hash.c551
-rw-r--r--src/benchmarks/eina/eina_bench_stringshare.c8
-rw-r--r--src/benchmarks/eina/eina_bench_stringshare_e17.c121
-rw-r--r--src/benchmarks/eina/meson.build4
10 files changed, 4 insertions, 1881 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index acba1b008e..d6879babc1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2188,10 +2188,8 @@ src/benchmarks/evas/evas_bench_saver.c
2188src/benchmarks/evas/evas_bench_loader.c 2188src/benchmarks/evas/evas_bench_loader.c
2189src/benchmarks/elementary/collection.c 2189src/benchmarks/elementary/collection.c
2190src/benchmarks/elementary/focus_widget_tree.c 2190src/benchmarks/elementary/focus_widget_tree.c
2191src/benchmarks/eina/eina_bench_stringshare_e17.c
2192src/benchmarks/eina/eina_bench_convert.c 2191src/benchmarks/eina/eina_bench_convert.c
2193src/benchmarks/eina/eina_bench_mempool.c 2192src/benchmarks/eina/eina_bench_mempool.c
2194src/benchmarks/eina/ecore_hash.c
2195src/benchmarks/eina/eina_bench_stringshare.c 2193src/benchmarks/eina/eina_bench_stringshare.c
2196src/benchmarks/eina/eina_bench_crc_hash.c 2194src/benchmarks/eina/eina_bench_crc_hash.c
2197src/benchmarks/eina/evas_object_list.c 2195src/benchmarks/eina/evas_object_list.c
@@ -2201,10 +2199,8 @@ src/benchmarks/eina/eina_bench_rectangle_pool.c
2201src/benchmarks/eina/eina_bench_quad.c 2199src/benchmarks/eina/eina_bench_quad.c
2202src/benchmarks/eina/evas_mempool.c 2200src/benchmarks/eina/evas_mempool.c
2203src/benchmarks/eina/eina_bench_array.c 2201src/benchmarks/eina/eina_bench_array.c
2204src/benchmarks/eina/ecore_strings.c
2205src/benchmarks/eina/eina_bench_sort.c 2202src/benchmarks/eina/eina_bench_sort.c
2206src/benchmarks/eina/ecore_list.c 2203src/benchmarks/eina/ecore_list.c
2207src/benchmarks/eina/evas_stringshare.c 2204src/benchmarks/eina/evas_stringshare.c
2208src/benchmarks/eina/ecore_sheap.c 2205src/benchmarks/eina/ecore_sheap.c
2209src/benchmarks/eina/eina_bench_hash.c
2210src/benchmarks/eina/evas_list.c 2206src/benchmarks/eina/evas_list.c
diff --git a/src/benchmarks/eina/Ecore_Data.h b/src/benchmarks/eina/Ecore_Data.h
index a085401242..e959eb59fc 100644
--- a/src/benchmarks/eina/Ecore_Data.h
+++ b/src/benchmarks/eina/Ecore_Data.h
@@ -299,76 +299,6 @@ EAPI int ecore_dlist_free_cb_set(Ecore_DList *dlist,
299 Ecore_Free_Cb free_func); 299 Ecore_Free_Cb free_func);
300 300
301 301
302
303/*
304 * Hash Table Implementation:
305 *
306 * Traditional hash table implementation. I had tried a list of tables
307 * approach to save on the realloc's but it ended up being much slower than
308 * the traditional approach.
309 */
310
311typedef struct _ecore_hash_node Ecore_Hash_Node;
312# define ECORE_HASH_NODE(hash) ((Ecore_Hash_Node *)hash)
313
314struct _ecore_hash_node
315{
316 Ecore_Hash_Node *next; /* Pointer to the next node in the bucket list */
317 void *key; /* The key for the data node */
318 void *value; /* The value associated with this node */
319};
320
321typedef struct _ecore_hash Ecore_Hash;
322# define ECORE_HASH(hash) ((Ecore_Hash *)hash)
323
324struct _ecore_hash
325{
326 Ecore_Hash_Node **buckets;
327 int size; /* An index into the table of primes to
328 determine size */
329 int nodes; /* The number of nodes currently in the hash */
330
331 int index; /* The current index into the bucket table */
332
333 Ecore_Compare_Cb compare; /* The function used to compare node values */
334 Ecore_Hash_Cb hash_func; /* The callback function to determine hash */
335
336 Ecore_Free_Cb free_key; /* The callback function to free key */
337 Ecore_Free_Cb free_value; /* The callback function to free value */
338};
339
340/* Create and initialize a hash */
341EAPI Ecore_Hash *ecore_hash_new(Ecore_Hash_Cb hash_func,
342 Ecore_Compare_Cb compare);
343EAPI int ecore_hash_init(Ecore_Hash *hash,
344 Ecore_Hash_Cb hash_func,
345 Ecore_Compare_Cb compare);
346
347/* Functions related to freeing the data in the hash table */
348EAPI int ecore_hash_free_key_cb_set(Ecore_Hash *hash,
349 Ecore_Free_Cb function);
350EAPI int ecore_hash_free_value_cb_set(Ecore_Hash *hash,
351 Ecore_Free_Cb function);
352EAPI void ecore_hash_destroy(Ecore_Hash *hash);
353
354EAPI int ecore_hash_count(Ecore_Hash *hash);
355EAPI int ecore_hash_for_each_node(Ecore_Hash *hash,
356 Ecore_For_Each for_each_func,
357 void *user_data);
358EAPI Ecore_List *ecore_hash_keys(Ecore_Hash *hash);
359
360/* Retrieve and store data into the hash */
361EAPI void * ecore_hash_get(Ecore_Hash *hash, const void *key);
362EAPI int ecore_hash_set(Ecore_Hash *hash, void *key, void *value);
363EAPI int ecore_hash_hash_set(Ecore_Hash *hash, Ecore_Hash *set);
364EAPI void * ecore_hash_remove(Ecore_Hash *hash, const void *key);
365EAPI void * ecore_hash_find(Ecore_Hash *hash,
366 Ecore_Compare_Cb compare,
367 const void *value);
368EAPI void ecore_hash_dump_graph(Ecore_Hash *hash);
369EAPI void ecore_hash_dump_stats(Ecore_Hash *hash);
370
371
372typedef struct _ecore_heap Ecore_Sheap; 302typedef struct _ecore_heap Ecore_Sheap;
373# define ECORE_HEAP(heap) ((Ecore_Sheap *)heap) 303# define ECORE_HEAP(heap) ((Ecore_Sheap *)heap)
374 304
@@ -415,11 +345,6 @@ struct _ecore_string
415 int references; 345 int references;
416}; 346};
417 347
418EAPI int ecore_string_init();
419EAPI int ecore_string_shutdown();
420EAPI const char *ecore_string_instance(const char *string);
421EAPI void ecore_string_release(const char *string);
422
423typedef struct _Ecore_Tree_Node Ecore_Tree_Node; 348typedef struct _Ecore_Tree_Node Ecore_Tree_Node;
424# define ECORE_TREE_NODE(object) ((Ecore_Tree_Node *)object) 349# define ECORE_TREE_NODE(object) ((Ecore_Tree_Node *)object)
425struct _Ecore_Tree_Node 350struct _Ecore_Tree_Node
diff --git a/src/benchmarks/eina/ecore_hash.c b/src/benchmarks/eina/ecore_hash.c
deleted file mode 100644
index 24ff219029..0000000000
--- a/src/benchmarks/eina/ecore_hash.c
+++ /dev/null
@@ -1,952 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8
9#include "Ecore_Data.h"
10
11#define PRIME_TABLE_MAX 21
12#define PRIME_MIN 17
13#define PRIME_MAX 16777213
14
15#define ECORE_HASH_CHAIN_MAX 3
16
17#define ECORE_COMPUTE_HASH(hash, key) hash->hash_func(key) % \
18 ecore_prime_table[hash->size];
19
20#define ECORE_HASH_INCREASE(hash) ((hash && ecore_prime_table[hash->size] < \
21 PRIME_MAX) ? \
22 (hash->nodes / \
23 ecore_prime_table[hash->size]) > \
24 ECORE_HASH_CHAIN_MAX : FALSE)
25#define ECORE_HASH_REDUCE(hash) ((hash && ecore_prime_table[hash->size] > \
26 PRIME_MIN) ? \
27 (double)hash->nodes / \
28 (double)ecore_prime_table[hash->size - 1] \
29 < ((double)ECORE_HASH_CHAIN_MAX * \
30 0.375) : FALSE)
31
32
33static const unsigned int ecore_prime_table[] =
34{
35 17, 31, 61, 127, 257, 509, 1021,
36 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573,
37 2097143, 4194301, 8388617, 16777213
38};
39
40
41/* Private hash manipulation functions */
42static int _ecore_hash_node_add(Ecore_Hash *hash,
43 Ecore_Hash_Node *node);
44static Ecore_Hash_Node * _ecore_hash_node_get(Ecore_Hash *hash,
45 const void *key);
46static int _ecore_hash_increase(Ecore_Hash *hash);
47static int _ecore_hash_decrease(Ecore_Hash *hash);
48static inline int _ecore_hash_rehash(Ecore_Hash *hash,
49 Ecore_Hash_Node **old_table,
50 int old_size);
51static int _ecore_hash_bucket_destroy(Ecore_Hash_Node *list,
52 Ecore_Free_Cb keyd,
53 Ecore_Free_Cb valued);
54static inline Ecore_Hash_Node *_ecore_hash_bucket_get(Ecore_Hash *hash,
55 Ecore_Hash_Node *bucket,
56 const void *key);
57
58static Ecore_Hash_Node * _ecore_hash_node_new(void *key, void *value);
59static int _ecore_hash_node_init(Ecore_Hash_Node *node,
60 void *key,
61 void *value);
62static int _ecore_hash_node_destroy(Ecore_Hash_Node *node,
63 Ecore_Free_Cb keyd,
64 Ecore_Free_Cb valued);
65
66/**
67 * @defgroup Ecore_Data_Hash_ADT_Creation_Group Hash Creation Functions
68 *
69 * Functions that create hash tables.
70 */
71
72/**
73 * Creates and initializes a new hash
74 * @param hash_func The function for determining hash position.
75 * @param compare The function for comparing node keys.
76 * @return @c NULL on error, a new hash on success.
77 * @ingroup Ecore_Data_Hash_ADT_Creation_Group
78 */
79EAPI Ecore_Hash *
80ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare)
81{
82 Ecore_Hash *new_hash = (Ecore_Hash *)malloc(sizeof(Ecore_Hash));
83 if (!new_hash)
84 return NULL;
85
86 if (!ecore_hash_init(new_hash, hash_func, compare))
87 {
88 FREE(new_hash);
89 return NULL;
90 }
91
92 return new_hash;
93}
94
95/**
96 * Initializes the given hash.
97 * @param hash The given hash.
98 * @param hash_func The function used for hashing node keys.
99 * @param compare The function used for comparing node keys.
100 * @return @c TRUE on success, @c FALSE on an error.
101 * @ingroup Ecore_Data_Hash_ADT_Creation_Group
102 */
103EAPI int
104ecore_hash_init(Ecore_Hash *hash,
105 Ecore_Hash_Cb hash_func,
106 Ecore_Compare_Cb compare)
107{
108 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
109
110 memset(hash, 0, sizeof(Ecore_Hash));
111
112 hash->hash_func = hash_func;
113 hash->compare = compare;
114
115 hash->buckets = (Ecore_Hash_Node **)calloc(ecore_prime_table[0],
116 sizeof(Ecore_Hash_Node *));
117
118 return TRUE;
119}
120
121/**
122 * @defgroup Ecore_Data_Hash_ADT_Destruction_Group Hash Destruction Functions
123 *
124 * Functions that destroy hash tables and their contents.
125 */
126
127/**
128 * Sets the function to destroy the keys of the given hash.
129 * @param hash The given hash.
130 * @param function The function used to free the node keys. NULL is a
131 * valid value and means that no function will be called.
132 * @return @c TRUE on success, @c FALSE on error.
133 * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
134 */
135EAPI int
136ecore_hash_free_key_cb_set(Ecore_Hash *hash, Ecore_Free_Cb function)
137{
138 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
139
140 hash->free_key = function;
141
142 return TRUE;
143}
144
145/**
146 * Sets the function to destroy the values in the given hash.
147 * @param hash The given hash.
148 * @param function The function that will free the node values. NULL is a
149 * valid value and means that no function will be called.
150 * @return @c TRUE on success, @c FALSE on error
151 * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
152 */
153EAPI int
154ecore_hash_free_value_cb_set(Ecore_Hash *hash, Ecore_Free_Cb function)
155{
156 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
157
158 hash->free_value = function;
159
160 return TRUE;
161}
162
163/**
164 * @defgroup Ecore_Data_Hash_ADT_Data_Group Hash Data Functions
165 *
166 * Functions that set, access and delete values from the hash tables.
167 */
168
169/**
170 * Sets a key-value pair in the given hash table.
171 * @param hash The given hash table.
172 * @param key The key.
173 * @param value The value.
174 * @return @c TRUE if successful, @c FALSE if not.
175 * @ingroup Ecore_Data_Hash_ADT_Data_Group
176 */
177EAPI int
178ecore_hash_set(Ecore_Hash *hash, void *key, void *value)
179{
180 int ret = FALSE;
181 Ecore_Hash_Node *node;
182
183 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
184
185 node = _ecore_hash_node_get(hash, key);
186 if (node)
187 {
188 if (hash->free_key)
189 hash->free_key(key);
190
191 if (node->value && hash->free_value)
192 hash->free_value(node->value);
193
194 node->value = value;
195 ret = TRUE;
196 }
197 else
198 {
199 node = _ecore_hash_node_new(key, value);
200 if (node)
201 ret = _ecore_hash_node_add(hash, node);
202 }
203
204 return ret;
205}
206
207/**
208 * Sets all key-value pairs from set in the given hash table.
209 * @param hash The given hash table.
210 * @param set The hash table to import.
211 * @return @c TRUE if successful, @c FALSE if not.
212 * @ingroup Ecore_Data_Hash_ADT_Data_Group
213 */
214EAPI int
215ecore_hash_hash_set(Ecore_Hash *hash, Ecore_Hash *set)
216{
217 unsigned int i;
218 Ecore_Hash_Node *node, *old;
219
220 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
221 CHECK_PARAM_POINTER_RETURN("set", set, FALSE);
222
223 for (i = 0; i < ecore_prime_table[set->size]; i++)
224 {
225 /* Hash into a new list to avoid loops of rehashing the same nodes */
226 while ((old = set->buckets[i]))
227 {
228 set->buckets[i] = old->next;
229 old->next = NULL;
230 node = _ecore_hash_node_get(hash, old->key);
231 if (node)
232 {
233 /* This key already exists. Delete the old and add the new
234 * value */
235 if (hash->free_key)
236 hash->free_key(node->key);
237
238 if (hash->free_value)
239 hash->free_value(node->value);
240
241 node->key = old->key;
242 node->value = old->value;
243 free(old);
244 }
245 else
246 _ecore_hash_node_add(hash, old);
247 }
248 }
249 FREE(set->buckets);
250 ecore_hash_init(set, set->hash_func, set->compare);
251 return TRUE;
252}
253
254/**
255 * @brief Frees the hash table and the data contained inside it.
256 * @param hash: The hash table to destroy.
257 * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
258 */
259EAPI void
260ecore_hash_destroy(Ecore_Hash *hash)
261{
262 unsigned int i = 0;
263
264 CHECK_PARAM_POINTER("hash", hash);
265
266 if (hash->buckets)
267 {
268 while (i < ecore_prime_table[hash->size])
269 {
270 if (hash->buckets[i])
271 {
272 Ecore_Hash_Node *bucket;
273
274 /*
275 * Remove the bucket list to avoid possible recursion
276 * on the free callbacks.
277 */
278 bucket = hash->buckets[i];
279 hash->buckets[i] = NULL;
280 _ecore_hash_bucket_destroy(bucket,
281 hash->free_key,
282 hash->free_value);
283 }
284
285 i++;
286 }
287
288 FREE(hash->buckets);
289 }
290
291 FREE(hash);
292
293 return;
294}
295
296/**
297 * @defgroup Ecore_Data_Hash_ADT_Traverse_Group Hash Traverse Functions
298 *
299 * Functions that iterate through hash tables.
300 */
301
302/**
303 * Counts the number of nodes in a hash table.
304 * @param hash The hash table to count current nodes.
305 * @return The number of nodes in the hash.
306 * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
307 */
308EAPI int
309ecore_hash_count(Ecore_Hash *hash)
310{
311 CHECK_PARAM_POINTER_RETURN("hash", hash, 0);
312
313 return hash->nodes;
314}
315
316/**
317 * Runs the @p for_each_func function on each entry in the given hash.
318 * @param hash The given hash.
319 * @param for_each_func The function that each entry is passed to.
320 * @param user_data a pointer passed to calls of for_each_func
321 * @return TRUE on success, FALSE otherwise.
322 * @ingroup Ecore_Data_Hash_ADT_Traverse_Group
323 */
324EAPI int
325ecore_hash_for_each_node(Ecore_Hash *hash,
326 Ecore_For_Each for_each_func,
327 void *user_data)
328{
329 unsigned int i = 0;
330
331 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
332 CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE);
333
334 while (i < ecore_prime_table[hash->size])
335 {
336 if (hash->buckets[i])
337 {
338 Ecore_Hash_Node *node;
339
340 for (node = hash->buckets[i]; node; node = node->next)
341 {
342 for_each_func(node, user_data);
343 }
344 }
345
346 i++;
347 }
348
349 return TRUE;
350}
351
352/**
353 * Retrieves an ecore_list of all keys in the given hash.
354 * @param hash The given hash.
355 * @return new ecore_list on success, NULL otherwise
356 * @ingroup Ecore_Data_Hash_ADT_Traverse_Group
357 */
358EAPI Ecore_List *
359ecore_hash_keys(Ecore_Hash *hash)
360{
361 unsigned int i = 0;
362 Ecore_List *keys;
363
364 CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
365
366 keys = ecore_list_new();
367 while (i < ecore_prime_table[hash->size])
368 {
369 if (hash->buckets[i])
370 {
371 Ecore_Hash_Node *node;
372
373 for (node = hash->buckets[i]; node; node = node->next)
374 {
375 ecore_list_append(keys, node->key);
376 }
377 }
378
379 i++;
380 }
381 ecore_list_first_goto(keys);
382
383 return keys;
384}
385
386/**
387 * Prints the distribution of the given hash table for graphing.
388 * @param hash The given hash table.
389 */
390EAPI void
391ecore_hash_dump_graph(Ecore_Hash *hash)
392{
393 unsigned int i;
394
395 for (i = 0; i < ecore_prime_table[hash->size]; i++)
396 if (hash->buckets[i])
397 {
398 unsigned int n = 0;
399 Ecore_Hash_Node *node;
400 for (node = hash->buckets[i]; node; node = node->next)
401 n++;
402 printf("%u\t%u", i, n);
403 }
404 else
405 printf("%u\t0", i);
406
407}
408
409/**
410 * Prints the distribution of the given hash table for graphing.
411 * @param hash The given hash table.
412 */
413EAPI void
414ecore_hash_dump_stats(Ecore_Hash *hash)
415{
416 unsigned int i;
417 double variance, sum_n_2 = 0, sum_n = 0;
418
419 if (!hash->size) return;
420 for (i = 0; i < ecore_prime_table[hash->size]; i++)
421 {
422 if (hash->buckets[i])
423 {
424 int n = 0;
425 Ecore_Hash_Node *node;
426 for (node = hash->buckets[i]; node; node = node->next)
427 n++;
428 sum_n_2 += ((double)n * (double)n);
429 sum_n += (double)n;
430 }
431 }
432 if (i)
433 {
434 variance = (sum_n_2 - ((sum_n * sum_n) / (double)i)) / (double)i;
435 printf("Average length: %f\n\tvariance^2: %f", (sum_n / (double)i),
436 variance);
437 }
438}
439
440static int
441_ecore_hash_bucket_destroy(Ecore_Hash_Node *list,
442 Ecore_Free_Cb keyd,
443 Ecore_Free_Cb valued)
444{
445 Ecore_Hash_Node *node;
446
447 CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
448
449 for (node = list; node; node = list)
450 {
451 list = list->next;
452 _ecore_hash_node_destroy(node, keyd, valued);
453 }
454
455 return TRUE;
456}
457
458/*
459 * @brief Add the node to the hash table
460 * @param hash: the hash table to add the key
461 * @param node: the node to add to the hash table
462 * @return Returns FALSE on error, TRUE on success
463 */
464static int
465_ecore_hash_node_add(Ecore_Hash *hash, Ecore_Hash_Node *node)
466{
467 size_t hash_val;
468
469 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
470 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
471
472 /* Check to see if the hash needs to be resized */
473 if (ECORE_HASH_INCREASE(hash))
474 _ecore_hash_increase(hash);
475
476 /* Compute the position in the table */
477 if (!hash->hash_func)
478 hash_val = (size_t)node->key % ecore_prime_table[hash->size];
479 else
480 hash_val = ECORE_COMPUTE_HASH(hash, node->key);
481
482 /* Prepend the node to the list at the index position */
483 node->next = hash->buckets[hash_val];
484 hash->buckets[hash_val] = node;
485 hash->nodes++;
486
487 return TRUE;
488}
489
490/**
491 * Retrieves the value associated with the given key from the given hash
492 * table.
493 * @param hash The given hash table.
494 * @param key The key to search for.
495 * @return The value corresponding to key on success, @c NULL otherwise.
496 * @ingroup Ecore_Data_Hash_ADT_Data_Group
497 */
498EAPI void *
499ecore_hash_get(Ecore_Hash *hash, const void *key)
500{
501 void *data;
502 Ecore_Hash_Node *node;
503
504 CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
505
506 node = _ecore_hash_node_get(hash, key);
507 if (!node)
508 return NULL;
509
510 data = node->value;
511
512 return data;
513}
514
515/**
516 * Removes the value associated with the given key in the given hash
517 * table.
518 * @param hash The given hash table.
519 * @param key The key to search for.
520 * @return The value corresponding to the key on success. @c NULL is
521 * returned if there is an error.
522 * @ingroup Ecore_Data_Hash_ADT_Data_Group
523 */
524EAPI void *
525ecore_hash_remove(Ecore_Hash *hash, const void *key)
526{
527 Ecore_Hash_Node *node = NULL;
528 Ecore_Hash_Node *list;
529 size_t hash_val;
530 void *ret = NULL;
531
532 CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
533
534 /* Compute the position in the table */
535 if (!hash->hash_func)
536 hash_val = (size_t)key % ecore_prime_table[hash->size];
537 else
538 hash_val = ECORE_COMPUTE_HASH(hash, key);
539
540 /*
541 * If their is a list that could possibly hold the key/value pair
542 * traverse it and remove the hash node.
543 */
544 if (hash->buckets[hash_val])
545 {
546 list = hash->buckets[hash_val];
547
548 /*
549 * Traverse the list to find the specified key
550 */
551 node = list;
552 if (hash->compare)
553 while ((node) && (hash->compare(node->key, key) != 0))
554 {
555 list = node;
556 node = node->next;
557 }
558 else
559 while ((node) && (node->key != key))
560 {
561 list = node;
562 node = node->next;
563 }
564
565 /*
566 * Remove the node with the matching key and free it's memory
567 */
568 if (node)
569 {
570 if (list == node)
571 hash->buckets[hash_val] = node->next;
572 else
573 list->next = node->next;
574
575 ret = node->value;
576 node->value = NULL;
577 _ecore_hash_node_destroy(node, hash->free_key, NULL);
578 hash->nodes--;
579 }
580 }
581
582 if (ECORE_HASH_REDUCE(hash))
583 _ecore_hash_decrease(hash);
584
585 return ret;
586}
587
588/**
589 * Retrieves the first value that matches
590 * table.
591 * @param hash The given hash table.
592 * @param key The key to search for.
593 * @return The value corresponding to key on success, @c NULL otherwise.
594 * @ingroup Ecore_Data_Hash_ADT_Data_Group
595 */
596EAPI void *
597ecore_hash_find(Ecore_Hash *hash, Ecore_Compare_Cb compare, const void *value)
598{
599 unsigned int i = 0;
600
601 CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
602 CHECK_PARAM_POINTER_RETURN("compare", compare, NULL);
603 CHECK_PARAM_POINTER_RETURN("value", value, NULL);
604
605 while (i < ecore_prime_table[hash->size])
606 {
607 if (hash->buckets[i])
608 {
609 Ecore_Hash_Node *node;
610
611 for (node = hash->buckets[i]; node; node = node->next)
612 {
613 if (!compare(node->value, value))
614 return node->value;
615 }
616 }
617
618 i++;
619 }
620
621 return NULL;
622}
623
624/*
625 * @brief Retrieve the node associated with key
626 * @param hash: the hash table to search for the key
627 * @param key: the key to search for in the hash table
628 * @return Returns NULL on error, node corresponding to key on success
629 */
630static Ecore_Hash_Node *
631_ecore_hash_node_get(Ecore_Hash *hash, const void *key)
632{
633 size_t hash_val;
634 Ecore_Hash_Node *node = NULL;
635
636 CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
637
638 if (!hash->buckets)
639 return NULL;
640
641 /* Compute the position in the table */
642 if (!hash->hash_func)
643 hash_val = (size_t)key % ecore_prime_table[hash->size];
644 else
645 hash_val = ECORE_COMPUTE_HASH(hash, key);
646
647 /* Grab the bucket at the specified position */
648 if (hash->buckets[hash_val])
649 {
650 node = _ecore_hash_bucket_get(hash, hash->buckets[hash_val], key);
651 /*
652 * Move matched node to the front of the list as it's likely
653 * to be searched for again soon.
654 */
655 if (node && node != hash->buckets[hash_val])
656 {
657 node->next = hash->buckets[hash_val];
658 hash->buckets[hash_val] = node;
659 }
660 }
661
662 return node;
663}
664
665/*
666 * @brief Search the hash bucket for a specified key
667 * @param hash: the hash table to retrieve the comparison function
668 * @param bucket: the list to search for the key
669 * @param key: the key to search for in the list
670 * @return Returns NULL on error or not found, the found node on success
671 */
672static inline Ecore_Hash_Node *
673_ecore_hash_bucket_get(Ecore_Hash *hash,
674 Ecore_Hash_Node *bucket,
675 const void *key)
676{
677 Ecore_Hash_Node *prev = NULL;
678 Ecore_Hash_Node *node = NULL;
679
680 /*
681 * Traverse the list to find the desired node, if the node is in the
682 * list, then return the node.
683 */
684 if (hash->compare)
685 for (node = bucket; node; node = node->next)
686 {
687 if (hash->compare(node->key, key) == 0)
688 break;
689
690 prev = node;
691 }
692 else
693 for (node = bucket; node; node = node->next)
694 {
695 if (node->key == key)
696 break;
697
698 prev = node;
699 }
700
701 /*
702 * Remove node from the list to replace it at the beginning.
703 */
704 if (node && prev)
705 {
706 prev->next = node->next;
707 node->next = NULL;
708 }
709
710 return node;
711}
712
713/*
714 * @brief Increase the size of the hash table by approx. 2 * current size
715 * @param hash: the hash table to increase the size of
716 * @return Returns TRUE on success, FALSE on error
717 */
718static int
719_ecore_hash_increase(Ecore_Hash *hash)
720{
721 void *old;
722
723 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
724
725 /* Max size reached so return FALSE */
726 if ((ecore_prime_table[hash->size] == PRIME_MAX) ||
727 (hash->size == PRIME_TABLE_MAX))
728 return FALSE;
729
730 /*
731 * Increase the size of the hash and save a pointer to the old data
732 */
733 hash->size++;
734 old = hash->buckets;
735
736 /*
737 * Allocate a new bucket area, of the new larger size
738 */
739 hash->buckets =
740 calloc(ecore_prime_table[hash->size], sizeof(Ecore_Hash_Node *));
741
742 /*
743 * Make sure the allocation succeeded, if not replace the old data and
744 * return a failure.
745 */
746 if (!hash->buckets)
747 {
748 hash->buckets = old;
749 hash->size--;
750 return FALSE;
751 }
752
753 hash->nodes = 0;
754
755 /*
756 * Now move all of the old data into the new bucket area
757 */
758 if (_ecore_hash_rehash(hash, old, hash->size - 1))
759 {
760 FREE(old);
761 return TRUE;
762 }
763
764 /*
765 * Free the old buckets regardless of success.
766 */
767 FREE(old);
768
769 return FALSE;
770}
771
772/*
773 * @brief Decrease the size of the hash table by < 1/2 * current size
774 * @param hash: the hash table to decrease the size of
775 * @return Returns TRUE on success, FALSE on error
776 */
777static int
778_ecore_hash_decrease(Ecore_Hash *hash)
779{
780 Ecore_Hash_Node **old;
781
782 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
783
784 if (ecore_prime_table[hash->size] == PRIME_MIN)
785 return FALSE;
786
787 /*
788 * Decrease the hash size and store a pointer to the old data
789 */
790 hash->size--;
791 old = hash->buckets;
792
793 /*
794 * Allocate a new area to store the data
795 */
796 hash->buckets = (Ecore_Hash_Node **)calloc(ecore_prime_table[hash->size],
797 sizeof(Ecore_Hash_Node *));
798
799 /*
800 * Make sure allocation succeeded otherwise rreturn to the previous
801 * state
802 */
803 if (!hash->buckets)
804 {
805 hash->buckets = old;
806 hash->size++;
807 return FALSE;
808 }
809
810 hash->nodes = 0;
811
812 if (_ecore_hash_rehash(hash, old, hash->size + 1))
813 {
814 FREE(old);
815 return TRUE;
816 }
817
818 return FALSE;
819}
820
821/*
822 * @brief Rehash the nodes of a table into the hash table
823 * @param hash: the hash to place the nodes of the table
824 * @param table: the table to remove the nodes from and place in hash
825 * @return Returns TRUE on success, FALSE on error
826 */
827static inline int
828_ecore_hash_rehash(Ecore_Hash *hash, Ecore_Hash_Node **old_table, int old_size)
829{
830 unsigned int i;
831 Ecore_Hash_Node *old;
832
833 CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
834 CHECK_PARAM_POINTER_RETURN("old_table", old_table, FALSE);
835
836 for (i = 0; i < ecore_prime_table[old_size]; i++)
837 {
838 /* Hash into a new list to avoid loops of rehashing the same nodes */
839 while ((old = old_table[i]))
840 {
841 old_table[i] = old->next;
842 old->next = NULL;
843 _ecore_hash_node_add(hash, old);
844 }
845 }
846
847 return TRUE;
848}
849
850/*
851 * @brief Create a new hash node for key and value storage
852 * @param key: the key for this node
853 * @param value: the value that the key references
854 * @return Returns NULL on error, a new hash node on success
855 */
856static Ecore_Hash_Node *
857_ecore_hash_node_new(void *key, void *value)
858{
859 Ecore_Hash_Node *node;
860
861 node = (Ecore_Hash_Node *)malloc(sizeof(Ecore_Hash_Node));
862 if (!node)
863 return NULL;
864
865 if (!_ecore_hash_node_init(node, key, value))
866 {
867 FREE(node);
868 return NULL;
869 }
870
871 return node;
872}
873
874/*
875 * @brief Initialize a hash node to some sane default values
876 * @param node: the node to set the values
877 * @param key: the key to reference this node
878 * @param value: the value that key refers to
879 * @return Returns TRUE on success, FALSE on error
880 */
881static int
882_ecore_hash_node_init(Ecore_Hash_Node *node, void *key, void *value)
883{
884 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
885
886 node->key = key;
887 node->value = value;
888
889 return TRUE;
890}
891
892/*
893 * @brief Destroy a node and call the specified callbacks to free data
894 * @param node: the node to be destroyed
895 * @param keyd: the function to free the key
896 * @param valued: the function to free the value
897 * @return Returns TRUE on success, FALSE on error
898 */
899static int
900_ecore_hash_node_destroy(Ecore_Hash_Node *node,
901 Ecore_Free_Cb keyd,
902 Ecore_Free_Cb valued)
903{
904 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
905
906 if (keyd)
907 keyd(node->key);
908
909 if (valued)
910 valued(node->value);
911
912 FREE(node);
913
914 return TRUE;
915}
916
917int
918ecore_str_compare(const void *key1, const void *key2)
919{
920 const char *k1, *k2;
921
922 if (!key1 || !key2)
923 return ecore_direct_compare(key1, key2);
924 else if (key1 == key2)
925 return 0;
926
927 k1 = key1;
928 k2 = key2;
929
930 return strcmp(k1, k2);
931}
932
933unsigned int
934ecore_str_hash(const void *key)
935{
936 int i;
937 unsigned int mask;
938 unsigned int value = 0;
939 const char *k = key;
940
941 if (!k)
942 return 0;
943
944 mask = (sizeof(unsigned int) * 8) - 1;
945
946 for (i = 0; k[i] != '\0'; i++)
947 {
948 value ^= ((unsigned int)k[i] << ((i * 5) & mask));
949 }
950
951 return value;
952}
diff --git a/src/benchmarks/eina/ecore_strings.c b/src/benchmarks/eina/ecore_strings.c
deleted file mode 100644
index e56235226c..0000000000
--- a/src/benchmarks/eina/ecore_strings.c
+++ /dev/null
@@ -1,164 +0,0 @@
1#include <stdlib.h>
2#include <string.h>
3
4#include "Ecore_Data.h"
5
6static void ecore_string_free_cb(void *data);
7
8static Ecore_Hash *ecore_strings = NULL;
9static int ecore_string_init_count = 0;
10
11/**
12 * @defgroup Ecore_String_Group String Instance Functions
13 *
14 * These functions allow you to store one copy of a string, and use it
15 * throughout your program.
16 *
17 * This is a method to reduce the number of duplicated strings kept in
18 * memory. It's pretty common for the same strings to be dynamically
19 * allocated repeatedly between applications and libraries, especially in
20 * circumstances where you could have multiple copies of a structure that
21 * allocates the string. So rather than duplicating and freeing these
22 * strings, you request a read-only pointer to an existing string and
23 * only incur the overhead of a hash lookup.
24 *
25 * It sounds like micro-optimizing, but profiling has shown this can have
26 * a significant impact as you scale the number of copies up. It improves
27 * string creation/destruction speed, reduces memory use and decreases
28 * memory fragmentation, so a win all-around.
29 */
30
31/**
32 * Initialize the ecore string internal structure.
33 * @return Zero on failure, non-zero on successful initialization.
34 */
35EAPI int
36ecore_string_init(void)
37{
38 /*
39 * No strings have been loaded at this point, so create the hash
40 * table for storing string info for later.
41 */
42 if (!ecore_string_init_count)
43 {
44 ecore_strings = ecore_hash_new(ecore_str_hash, ecore_str_compare);
45 if (!ecore_strings)
46 return 0;
47
48 ecore_hash_free_value_cb_set(ecore_strings, ecore_string_free_cb);
49 }
50
51 ecore_string_init_count++;
52
53 return 1;
54}
55
56/**
57 * Retrieves an instance of a string for use in an ecore program.
58 * @param string The string to retrieve an instance of.
59 * @return A pointer to an instance of the string on success.
60 * @c NULL on failure.
61 * @ingroup Ecore_String_Group
62 */
63EAPI const char *
64ecore_string_instance(const char *string)
65{
66 Ecore_String *str;
67
68 CHECK_PARAM_POINTER_RETURN("string", string, NULL);
69
70 /*
71 * Check for a previous instance of the string, if not found, create
72 * it.
73 */
74 str = ecore_hash_get(ecore_strings, string);
75 if (!str)
76 {
77 int length;
78
79 /*
80 * Allocate and initialize a new string reference.
81 */
82 length = strlen(string) + 1;
83
84 str =
85 (Ecore_String *)malloc(sizeof(Ecore_String) + length * sizeof(char));
86 if (!str) return NULL;
87
88 str->string = (char *)(str + 1);
89 str->references = 0;
90
91 memcpy(str->string, string, length);
92
93 ecore_hash_set(ecore_strings, str->string, str);
94 }
95
96 str->references++;
97
98 return str->string;
99}
100
101/**
102 * Notes that the given string has lost an instance.
103 *
104 * It will free the string if no other instances are left.
105 *
106 * @param string The given string.
107 * @ingroup Ecore_String_Group
108 */
109EAPI void
110ecore_string_release(const char *string)
111{
112 Ecore_String *str;
113
114 CHECK_PARAM_POINTER("string", string);
115
116 str = ecore_hash_get(ecore_strings, (char *)string);
117 if (!str)
118 return;
119
120 str->references--;
121 if (str->references < 1)
122 {
123 ecore_hash_remove(ecore_strings, (char *)string);
124 FREE(str);
125 }
126}
127
128EAPI void
129ecore_string_hash_dump_graph(void)
130{
131 ecore_hash_dump_graph(ecore_strings);
132}
133
134EAPI void
135ecore_string_hash_dump_stats(void)
136{
137 ecore_hash_dump_stats(ecore_strings);
138}
139
140/**
141 * Shutdown the ecore string internal structures
142 * @return 0 when the module is completely shut down, 1 or
143 * greater otherwise.
144 */
145EAPI int
146ecore_string_shutdown(void)
147{
148 --ecore_string_init_count;
149 if (!ecore_string_init_count)
150 {
151 ecore_hash_destroy(ecore_strings);
152 ecore_strings = NULL;
153 }
154 return ecore_string_init_count;
155}
156
157static void
158ecore_string_free_cb(void *data)
159{
160 Ecore_String *str;
161
162 str = data;
163 FREE(str);
164}
diff --git a/src/benchmarks/eina/eina_bench.c b/src/benchmarks/eina/eina_bench.c
index 1ca7e51c18..5d758485f6 100644
--- a/src/benchmarks/eina/eina_bench.c
+++ b/src/benchmarks/eina/eina_bench.c
@@ -36,7 +36,6 @@ struct _Eina_Benchmark_Case
36}; 36};
37 37
38static const Eina_Benchmark_Case etc[] = { 38static const Eina_Benchmark_Case etc[] = {
39 { "Hash", eina_bench_hash, EINA_TRUE },
40 { "Hash_Short_Key", eina_bench_crc_hash_short, EINA_TRUE }, 39 { "Hash_Short_Key", eina_bench_crc_hash_short, EINA_TRUE },
41 { "Hash_Medium_Key", eina_bench_crc_hash_medium, EINA_TRUE }, 40 { "Hash_Medium_Key", eina_bench_crc_hash_medium, EINA_TRUE },
42 { "Hash_Large_key", eina_bench_crc_hash_large, EINA_TRUE }, 41 { "Hash_Large_key", eina_bench_crc_hash_large, EINA_TRUE },
@@ -129,8 +128,6 @@ main(int argc, char **argv)
129 break; 128 break;
130 } 129 }
131 130
132 eina_bench_e17();
133
134 eina_shutdown(); 131 eina_shutdown();
135 132
136 _mempool_shutdown(); 133 _mempool_shutdown();
diff --git a/src/benchmarks/eina/eina_bench.h b/src/benchmarks/eina/eina_bench.h
index 747ac6f39f..053bbba793 100644
--- a/src/benchmarks/eina/eina_bench.h
+++ b/src/benchmarks/eina/eina_bench.h
@@ -36,7 +36,4 @@ void eina_bench_rectangle_pool(Eina_Benchmark *bench);
36void eina_bench_quadtree(Eina_Benchmark *bench); 36void eina_bench_quadtree(Eina_Benchmark *bench);
37void eina_bench_promise(Eina_Benchmark *bench); 37void eina_bench_promise(Eina_Benchmark *bench);
38 38
39/* Specific benchmark. */
40void eina_bench_e17(void);
41
42#endif 39#endif
diff --git a/src/benchmarks/eina/eina_bench_hash.c b/src/benchmarks/eina/eina_bench_hash.c
deleted file mode 100644
index 96748183e0..0000000000
--- a/src/benchmarks/eina/eina_bench_hash.c
+++ /dev/null
@@ -1,551 +0,0 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <time.h>
27
28#ifdef EINA_BENCH_HAVE_GLIB
29# include <glib.h>
30#endif
31
32#include "Evas_Data.h"
33#include "Ecore_Data.h"
34
35#include "eina_hash.h"
36#include "eina_array.h"
37#include "eina_bench.h"
38#include "eina_rbtree.h"
39#include "eina_convert.h"
40
41#ifdef CITYHASH_BENCH
42// Hash function for a byte array.
43uint64_t CityHash64(const char *buf, size_t len);
44
45static int
46city_hash(const char *buf, int len)
47{
48 return (int)CityHash64(buf, len);
49}
50
51static unsigned int
52_eina_string_key_length(const char *key)
53{
54 if (!key)
55 return 0;
56
57 return (int)strlen(key) + 1;
58}
59
60static int
61_eina_string_key_cmp(const char *key1, EINA_UNUSED int key1_length,
62 const char *key2, EINA_UNUSED int key2_length)
63{
64 return strcmp(key1, key2);
65}
66#endif
67
68
69typedef struct _Eina_Bench_Rbtree Eina_Bench_Rbtree;
70struct _Eina_Bench_Rbtree
71{
72 Eina_Rbtree node;
73 char key[10];
74 int value;
75};
76
77static Eina_Rbtree_Direction
78_eina_bench_rbtree_cmp(const Eina_Bench_Rbtree *left,
79 const Eina_Bench_Rbtree *right,
80 EINA_UNUSED void *data)
81{
82 if (!left)
83 return EINA_RBTREE_RIGHT;
84
85 if (!right)
86 return EINA_RBTREE_LEFT;
87
88 return strcmp(left->key,
89 right->key) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
90}
91
92static inline int
93_eina_bench_rbtree_key(const Eina_Bench_Rbtree *node,
94 const char *key,
95 int length,
96 EINA_UNUSED void *data)
97{
98 return strncmp(node->key, key, length);
99}
100
101static void
102_eina_bench_rbtree_free(Eina_Rbtree *node, EINA_UNUSED void *data)
103{
104 free(node);
105}
106
107static void
108eina_bench_lookup_rbtree(int request)
109{
110 Eina_Rbtree *root = NULL;
111 int i;
112 int j;
113
114 for (i = 0; i < request; ++i)
115 {
116 Eina_Bench_Rbtree *tmp;
117
118 tmp = malloc(sizeof (Eina_Bench_Rbtree));
119 if (!tmp)
120 continue;
121
122 tmp->value = i;
123 eina_convert_itoa(i, tmp->key);
124
125 root = eina_rbtree_inline_insert(root,
126 &tmp->node,
127 EINA_RBTREE_CMP_NODE_CB(
128 _eina_bench_rbtree_cmp),
129 NULL);
130 }
131
132 srand(time(NULL));
133
134 for (j = 0; j < 200; ++j)
135 for (i = 0; i < request; ++i)
136 {
137 Eina_Rbtree *tmp;
138 char tmp_key[10];
139
140 eina_convert_itoa(rand() % request, tmp_key);
141
142 tmp = eina_rbtree_inline_lookup(root,
143 tmp_key,
144 10,
145 EINA_RBTREE_CMP_KEY_CB(
146 _eina_bench_rbtree_key),
147 NULL);
148 /* Suppress warnings as we really don't want to do anything. */
149 (void) tmp;
150 }
151
152 eina_rbtree_delete(root, EINA_RBTREE_FREE_CB(_eina_bench_rbtree_free), NULL);
153}
154
155static void
156eina_bench_lookup_murmur(int request)
157{
158 Eina_Hash *hash = NULL;
159 int *tmp_val;
160 unsigned int i;
161 unsigned int j;
162
163 hash = eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
164 EINA_KEY_CMP(_eina_string_key_cmp),
165 EINA_KEY_HASH(eina_hash_murmur3),
166 free,
167 8);
168
169 for (i = 0; i < (unsigned int)request; ++i)
170 {
171 char tmp_key[10];
172
173 tmp_val = malloc(sizeof (int));
174
175 if (!tmp_val)
176 continue;
177
178 eina_convert_itoa(i, tmp_key);
179 *tmp_val = i;
180
181 eina_hash_add(hash, tmp_key, tmp_val);
182 }
183
184 srand(time(NULL));
185
186 for (j = 0; j < 200; ++j)
187 for (i = 0; i < (unsigned int)request; ++i)
188 {
189 char tmp_key[10];
190
191 eina_convert_itoa(rand() % request, tmp_key);
192 tmp_val = eina_hash_find(hash, tmp_key);
193 }
194
195 eina_hash_free(hash);
196}
197
198#ifdef CITYHASH_BENCH
199static void
200eina_bench_lookup_cityhash(int request)
201{
202 Eina_Hash *hash = NULL;
203 int *tmp_val;
204 unsigned int i;
205 unsigned int j;
206
207 hash = eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
208 EINA_KEY_CMP(_eina_string_key_cmp),
209 EINA_KEY_HASH(city_hash),
210 free,
211 8);
212
213 for (i = 0; i < (unsigned int)request; ++i)
214 {
215 char tmp_key[10];
216
217 tmp_val = malloc(sizeof (int));
218
219 if (!tmp_val)
220 continue;
221
222 eina_convert_itoa(i, tmp_key);
223 *tmp_val = i;
224
225 eina_hash_add(hash, tmp_key, tmp_val);
226 }
227
228 srand(time(NULL));
229
230 for (j = 0; j < 200; ++j)
231 for (i = 0; i < (unsigned int)request; ++i)
232 {
233 char tmp_key[10];
234
235 eina_convert_itoa(rand() % request, tmp_key);
236 tmp_val = eina_hash_find(hash, tmp_key);
237 }
238
239 eina_hash_free(hash);
240}
241#endif
242
243static void
244eina_bench_lookup_superfast(int request)
245{
246 Eina_Hash *hash = NULL;
247 int *tmp_val;
248 unsigned int i;
249 unsigned int j;
250
251 hash = eina_hash_string_superfast_new(free);
252
253 for (i = 0; i < (unsigned int)request; ++i)
254 {
255 char tmp_key[10];
256
257 tmp_val = malloc(sizeof (int));
258
259 if (!tmp_val)
260 continue;
261
262 eina_convert_itoa(i, tmp_key);
263 *tmp_val = i;
264
265 eina_hash_add(hash, tmp_key, tmp_val);
266 }
267
268 srand(time(NULL));
269
270 for (j = 0; j < 200; ++j)
271 for (i = 0; i < (unsigned int)request; ++i)
272 {
273 char tmp_key[10];
274
275 eina_convert_itoa(rand() % request, tmp_key);
276 tmp_val = eina_hash_find(hash, tmp_key);
277 }
278
279 eina_hash_free(hash);
280}
281
282static void
283eina_bench_lookup_djb2(int request)
284{
285 Eina_Hash *hash = NULL;
286 int *tmp_val;
287 unsigned int i;
288 unsigned int j;
289
290 hash = eina_hash_string_djb2_new(free);
291
292 for (i = 0; i < (unsigned int)request; ++i)
293 {
294 char tmp_key[10];
295
296 tmp_val = malloc(sizeof (int));
297
298 if (!tmp_val)
299 continue;
300
301 eina_convert_itoa(i, tmp_key);
302 *tmp_val = i;
303
304 eina_hash_add(hash, tmp_key, tmp_val);
305 }
306
307 srand(time(NULL));
308
309 for (j = 0; j < 200; ++j)
310 for (i = 0; i < (unsigned int)request; ++i)
311 {
312 char tmp_key[10];
313
314 eina_convert_itoa(rand() % request, tmp_key);
315
316 tmp_val = eina_hash_find(hash, tmp_key);
317 }
318
319 eina_hash_free(hash);
320}
321
322typedef struct _Eina_Bench_DJB2 Eina_Bench_DJB2;
323struct _Eina_Bench_DJB2
324{
325 char *key;
326 int value;
327};
328
329static void
330eina_bench_lookup_djb2_inline(int request)
331{
332 Eina_Hash *hash = NULL;
333 Eina_Bench_DJB2 *elm;
334 unsigned int i;
335 unsigned int j;
336
337 hash = eina_hash_string_djb2_new(free);
338
339 for (i = 0; i < (unsigned int)request; ++i)
340 {
341 int length;
342
343 elm = malloc(sizeof (Eina_Bench_DJB2) + 10);
344 if (!elm)
345 continue;
346
347 elm->key = (char *)(elm + 1);
348
349 length = eina_convert_itoa(i, elm->key) + 1;
350 elm->value = i;
351
352 eina_hash_direct_add_by_hash(hash, elm->key, length,
353 eina_hash_djb2(elm->key, length), elm);
354 }
355
356 srand(time(NULL));
357
358 for (j = 0; j < 200; ++j)
359 for (i = 0; i < (unsigned int)request; ++i)
360 {
361 char tmp_key[10];
362 int length = eina_convert_itoa(rand() % request, tmp_key) + 1;
363
364 elm =
365 eina_hash_find_by_hash(hash, tmp_key, length,
366 eina_hash_djb2(tmp_key, length));
367 }
368
369 eina_hash_free(hash);
370}
371
372#ifdef EINA_BENCH_HAVE_GLIB
373typedef struct _Eina_Bench_Glib Eina_Bench_Glib;
374struct _Eina_Bench_Glib
375{
376 char *key;
377 int value;
378};
379
380static void
381eina_bench_lookup_ghash(int request)
382{
383 Eina_Bench_Glib *elm;
384 GHashTable *hash;
385 unsigned int i;
386 unsigned int j;
387
388 hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
389
390 for (i = 0; i < (unsigned int)request; ++i)
391 {
392 elm = malloc(sizeof (Eina_Bench_Glib) + 10);
393 if (!elm)
394 continue;
395
396 elm->key = (char *)(elm + 1);
397
398 eina_convert_itoa(i, elm->key);
399 elm->value = i;
400
401 g_hash_table_insert(hash, elm->key, elm);
402 }
403
404 srand(time(NULL));
405
406 for (j = 0; j < 200; ++j)
407 for (i = 0; i < (unsigned int)request; ++i)
408 {
409 char tmp_key[10];
410
411 eina_convert_itoa(rand() % request, tmp_key);
412
413 elm = g_hash_table_lookup(hash, tmp_key);
414 }
415
416 g_hash_table_destroy(hash);
417}
418#endif
419
420static void
421eina_bench_lookup_evas(int request)
422{
423 Evas_Hash *hash = NULL;
424 Eina_Array *array = NULL;
425 int *tmp_val;
426 Eina_Array_Iterator it;
427 unsigned int i;
428 unsigned int j;
429
430 array = eina_array_new(10000);
431
432 for (i = 0; i < (unsigned int)request; ++i)
433 {
434 char tmp_key[10];
435
436 tmp_val = malloc(sizeof (int));
437
438 if (!tmp_val)
439 continue;
440
441 eina_convert_itoa(i, tmp_key);
442 *tmp_val = i;
443
444 hash = evas_hash_add(hash, tmp_key, tmp_val);
445
446 eina_array_push(array, tmp_val);
447 }
448
449 srand(time(NULL));
450
451 for (j = 0; j < 200; ++j)
452 for (i = 0; i < (unsigned int)request; ++i)
453 {
454 char tmp_key[10];
455
456 eina_convert_itoa(rand() % request, tmp_key);
457
458 tmp_val = evas_hash_find(hash, tmp_key);
459 }
460
461 evas_hash_free(hash);
462
463 EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
464 free(tmp_val);
465
466 eina_array_free(array);
467}
468
469typedef struct _Eina_Bench_Ecore Eina_Bench_Ecore;
470struct _Eina_Bench_Ecore
471{
472 char *key;
473 int value;
474};
475
476static void
477eina_bench_lookup_ecore(int request)
478{
479 Ecore_Hash *hash = NULL;
480 Eina_Bench_Ecore *elm;
481 unsigned int i;
482 unsigned int j;
483
484 hash = ecore_hash_new(ecore_str_hash, ecore_str_compare);
485
486 ecore_hash_free_key_cb_set(hash, NULL);
487 ecore_hash_free_value_cb_set(hash, free);
488
489 for (i = 0; i < (unsigned int)request; ++i)
490 {
491 elm = malloc(sizeof (Eina_Bench_Ecore) + 10);
492 if (!elm)
493 continue;
494
495 elm->key = (char *)(elm + 1);
496 eina_convert_itoa(i, elm->key);
497 elm->value = i;
498
499 ecore_hash_set(hash, elm->key, elm);
500 }
501
502 srand(time(NULL));
503
504 for (j = 0; j < 200; ++j)
505 for (i = 0; i < (unsigned int)request; ++i)
506 {
507 char tmp_key[10];
508
509 eina_convert_itoa(rand() % request, tmp_key);
510
511 elm = ecore_hash_get(hash, tmp_key);
512 }
513
514 ecore_hash_destroy(hash);
515}
516
517void eina_bench_hash(Eina_Benchmark *bench)
518{
519 eina_benchmark_register(bench, "superfast-lookup",
520 EINA_BENCHMARK(
521 eina_bench_lookup_superfast), 10, 10000, 10);
522 eina_benchmark_register(bench, "djb2-lookup",
523 EINA_BENCHMARK(
524 eina_bench_lookup_djb2), 10, 10000, 10);
525 eina_benchmark_register(bench, "djb2-lookup-inline",
526 EINA_BENCHMARK(
527 eina_bench_lookup_djb2_inline), 10, 10000, 10);
528 eina_benchmark_register(bench, "murmur",
529 EINA_BENCHMARK(
530 eina_bench_lookup_murmur), 10, 10000, 10);
531#ifdef CITYHASH_BENCH
532 eina_benchmark_register(bench, "cityhash",
533 EINA_BENCHMARK(
534 eina_bench_lookup_cityhash), 10, 10000, 10);
535#endif
536 eina_benchmark_register(bench, "rbtree",
537 EINA_BENCHMARK(
538 eina_bench_lookup_rbtree), 10, 10000, 10);
539#ifdef EINA_BENCH_HAVE_GLIB
540 eina_benchmark_register(bench, "ghash-lookup",
541 EINA_BENCHMARK(
542 eina_bench_lookup_ghash), 10, 10000, 10);
543#endif
544 eina_benchmark_register(bench, "evas-lookup",
545 EINA_BENCHMARK(
546 eina_bench_lookup_evas), 10, 10000, 10);
547 eina_benchmark_register(bench, "ecore-lookup",
548 EINA_BENCHMARK(
549 eina_bench_lookup_ecore), 10, 10000, 10);
550
551}
diff --git a/src/benchmarks/eina/eina_bench_stringshare.c b/src/benchmarks/eina/eina_bench_stringshare.c
index 22d18fa485..1b19154493 100644
--- a/src/benchmarks/eina/eina_bench_stringshare.c
+++ b/src/benchmarks/eina/eina_bench_stringshare.c
@@ -139,14 +139,14 @@ eina_bench_ecore_job(int request)
139 unsigned int j; 139 unsigned int j;
140 int i; 140 int i;
141 141
142 ecore_string_init(); 142 //ecore_string_init();
143 143
144 for (i = 0; i < request; ++i) 144 for (i = 0; i < request; ++i)
145 { 145 {
146 char build[64] = "string_"; 146 char build[64] = "string_";
147 147
148 eina_convert_xtoa(i, build + 7); 148 eina_convert_xtoa(i, build + 7);
149 tmp = ecore_string_instance(build); 149 //tmp = ecore_string_instance(build);
150 } 150 }
151 151
152 srand(time(NULL)); 152 srand(time(NULL));
@@ -157,13 +157,13 @@ eina_bench_ecore_job(int request)
157 char build[64] = "string_"; 157 char build[64] = "string_";
158 158
159 eina_convert_xtoa(rand() % request, build + 7); 159 eina_convert_xtoa(rand() % request, build + 7);
160 tmp = ecore_string_instance(build); 160 //tmp = ecore_string_instance(build);
161 } 161 }
162 162
163 /* Suppress warnings as we really don't want to do anything. */ 163 /* Suppress warnings as we really don't want to do anything. */
164 (void) tmp; 164 (void) tmp;
165 165
166 ecore_string_shutdown(); 166 //ecore_string_shutdown();
167} 167}
168 168
169void eina_bench_stringshare(Eina_Benchmark *bench) 169void eina_bench_stringshare(Eina_Benchmark *bench)
diff --git a/src/benchmarks/eina/eina_bench_stringshare_e17.c b/src/benchmarks/eina/eina_bench_stringshare_e17.c
deleted file mode 100644
index 2b2b45cb34..0000000000
--- a/src/benchmarks/eina/eina_bench_stringshare_e17.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <time.h>
26
27#ifdef EINA_BENCH_HAVE_GLIB
28# include <glib.h>
29#endif
30
31#include "Evas_Data.h"
32#include "Ecore_Data.h"
33
34#include "Eina.h"
35
36#if EINA_ENABLE_BENCH_E17
37
38typedef struct _Eina_Stringshare_Test Eina_Stringshare_Test;
39struct _Eina_Stringshare_Test
40{
41 const char *name;
42
43 int (*init)(void);
44 const char *(*add)(const char *str);
45 void (*del)(const char *str);
46 int (*shutdown)(void);
47};
48
49static Eina_Stringshare_Test eina_str = {
50 "eina",
51 eina_init,
52 eina_stringshare_add,
53 eina_stringshare_del,
54 eina_shutdown
55};
56
57static Eina_Stringshare_Test evas_str = {
58 "evas",
59 NULL,
60 evas_stringshare_add,
61 evas_stringshare_del,
62 NULL
63};
64
65static Eina_Stringshare_Test ecore_str = {
66 "ecore",
67 ecore_string_init,
68 ecore_string_instance,
69 ecore_string_release,
70 ecore_string_shutdown
71};
72
73static Eina_Stringshare_Test *tests[] = {
74 &eina_str,
75 &evas_str,
76 &ecore_str,
77 NULL
78};
79
80static void
81eina_bench_e17_stringshare(Eina_Stringshare_Test *str)
82{
83 Eina_Counter *cnt;
84 char *result;
85
86 cnt = eina_counter_new(str->name);
87
88 eina_counter_start(cnt);
89
90 if (str->init)
91 str->init();
92
93//#include "strlog"
94
95 if (str->shutdown)
96 str->shutdown();
97
98 eina_counter_stop(cnt, 1);
99
100 result = eina_counter_dump(cnt);
101 fprintf(stderr, "For `%s`:\n%s\n", str->name, result);
102 free(result);
103
104 eina_counter_free(cnt);
105}
106#endif
107
108void
109eina_bench_e17(void)
110{
111#if EINA_ENABLE_BENCH_E17
112 int i;
113
114 eina_init();
115
116 for (i = 0; tests[i]; ++i)
117 eina_bench_e17_stringshare(tests[i]);
118
119 eina_shutdown();
120#endif
121}
diff --git a/src/benchmarks/eina/meson.build b/src/benchmarks/eina/meson.build
index ba126987fb..8243511d6e 100644
--- a/src/benchmarks/eina/meson.build
+++ b/src/benchmarks/eina/meson.build
@@ -1,17 +1,13 @@
1eina_bench_src = files( 1eina_bench_src = files(
2'eina_bench.c', 2'eina_bench.c',
3'eina_bench_sort.c', 3'eina_bench_sort.c',
4'eina_bench_hash.c',
5'eina_bench_crc_hash.c', 4'eina_bench_crc_hash.c',
6'eina_bench_stringshare.c', 5'eina_bench_stringshare.c',
7'eina_bench_convert.c', 6'eina_bench_convert.c',
8'eina_bench_mempool.c', 7'eina_bench_mempool.c',
9'eina_bench_stringshare_e17.c',
10'eina_bench_array.c', 8'eina_bench_array.c',
11'eina_bench_rectangle_pool.c', 9'eina_bench_rectangle_pool.c',
12'ecore_list.c', 10'ecore_list.c',
13'ecore_strings.c',
14'ecore_hash.c',
15'ecore_sheap.c', 11'ecore_sheap.c',
16'evas_hash.c', 12'evas_hash.c',
17'evas_list.c', 13'evas_list.c',