cedric pushed a commit to branch master.
commit c435968f6965551c1e9d6103efe3261e884646f6
Author: Cedric Bail <[email protected]>
Date: Mon Jul 1 17:09:02 2013 +0900
eo: a little more inlining, give me a 10% speed improvement.
---
src/Makefile_Eo.am | 2 +-
src/lib/eo/eo_private.h | 8 +-
src/lib/eo/eo_ptr_indirection.c | 498 +--------------------
src/lib/eo/eo_ptr_indirection.h | 2 +
.../{eo_ptr_indirection.c => eo_ptr_indirection.x} | 29 +-
5 files changed, 22 insertions(+), 517 deletions(-)
diff --git a/src/Makefile_Eo.am b/src/Makefile_Eo.am
index e955632..ab24350 100644
--- a/src/Makefile_Eo.am
+++ b/src/Makefile_Eo.am
@@ -154,4 +154,4 @@ TESTS += tests/eo/test_signals
endif
-EXTRA_DIST += tests/eo/eunit_tests.h
+EXTRA_DIST += tests/eo/eunit_tests.h lib/eo/eo_ptr_indirection.x
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index 4332383..b236b08 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -59,16 +59,16 @@ typedef struct _Eo_Class _Eo_Class;
typedef struct _Eo_Internal _Eo;
/* Retrieves the pointer to the object from the id */
-_Eo *_eo_obj_pointer_get(const Eo_Id obj_id);
+static inline _Eo *_eo_obj_pointer_get(const Eo_Id obj_id);
/* Allocates an entry for the given object */
-Eo_Id _eo_id_allocate(const _Eo *obj);
+static inline Eo_Id _eo_id_allocate(const _Eo *obj);
/* Releases an entry by the object id */
-void _eo_id_release(const Eo_Id obj_id);
+static inline void _eo_id_release(const Eo_Id obj_id);
/* Free all the entries and the tables */
-void _eo_free_ids_tables();
+static inline void _eo_free_ids_tables(void);
void _eo_condtor_done(Eo *obj);
diff --git a/src/lib/eo/eo_ptr_indirection.c b/src/lib/eo/eo_ptr_indirection.c
index 3bb28c1..ee55901 100644
--- a/src/lib/eo/eo_ptr_indirection.c
+++ b/src/lib/eo/eo_ptr_indirection.c
@@ -3,507 +3,15 @@
#endif
#include "eo_ptr_indirection.h"
-#include <assert.h>
-#ifdef __linux__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#endif
-
-/* Start of pointer indirection:
- *
- * This feature is responsible of hiding from the developer the real pointer of
- * the Eo object to supply a better memory management by preventing bad usage
- * of the pointers.
- *
- * Eo * is no more a pointer but indexes to an entry into an ids table.
- * For a better memory usage:
- * - a tree structure is used, composed of a top level table pointing at
- * mid tables pointing at tables composed of entries.
- * - tables are allocated when needed (i.e no more empty entries in allocated
tables.
- * - empty tables are freed, except one kept as spare table.
- *
- * An Eo id is contructed by bits manipulation of table indexes and a
generation.
- *
- * id = Mid Table | Table | Entry | Generation
- *
- * Generation helps finding abuse of ids. When an entry is assigned to an
- * object, a generation is inserted into the id. If the developer uses this id
- * although the object is freed and another one has replaced it into the same
- * entry of the table, the generation will be different and an error will
- * occur when accessing with the old id.
- *
- * Each Table is composed of:
- * - an index 'start' indicating which free entry is the next one to use.
- * - 2 indexes 'fifo_head' and 'fifo_tail' defining a fifo,
- * that will help us to store the entries to be reused. It stores only the
- * entries that have been used at least one time. The entries that have
- * never been used are "pointed" by the start parameter.
- * - entries composed of:
- * - a pointer to the object
- * - an index 'next_in_fifo' used to chain the free entries in the fifo
- * - a flag indicating if the entry is active
- * - a generation assigned to the object
- *
- * When an entry is searched into a table, we first use one of the entries that
- * has never been used. If there is none, we try to pop from the fifo.
- * If a such entry doesn't exist, we pass to the next table.
- * When an entry is found, we reserve it to the object pointer
- * then contruct and return the related Eo id.
- *
- * Assigning all the entries of a table before trying to reuse them from
- * the fifo ensures that we are not going to soon recycle a released entry,
- * thus minimize the risks of an aggressive del() then use() on a single entry.
- *
- * The indexes and a reference to the last table which served an entry is kept
- * and is reused prior to the others untill it is full.
- * When an object is freed, the entry into the table is released by appending
- * it to the fifo.
- */
-
-#if SIZEOF_UINTPTR_T == 4
-/* 32 bits */
-# define BITS_MID_TABLE_ID 5
-# define BITS_TABLE_ID 5
-# define BITS_ENTRY_ID 12
-# define BITS_GENERATION_COUNTER 10
-# define DROPPED_TABLES 0
-# define DROPPED_ENTRIES 4
-typedef int16_t Table_Index;
-typedef uint16_t Generation_Counter;
-#else
-/* 64 bits */
-# define BITS_MID_TABLE_ID 11
-# define BITS_TABLE_ID 11
-# define BITS_ENTRY_ID 12
-# define BITS_GENERATION_COUNTER 30
-# define DROPPED_TABLES 2
-# define DROPPED_ENTRIES 3
-typedef int16_t Table_Index;
-typedef uint32_t Generation_Counter;
-#endif
-
-/* Shifts macros to manipulate the Eo id */
-#define SHIFT_MID_TABLE_ID (BITS_TABLE_ID + \
- BITS_ENTRY_ID + BITS_GENERATION_COUNTER)
-#define SHIFT_TABLE_ID (BITS_ENTRY_ID + BITS_GENERATION_COUNTER)
-#define SHIFT_ENTRY_ID (BITS_GENERATION_COUNTER)
-
-/* Maximum ranges - a few tables and entries are dropped to minimize the amount
- * of wasted bytes, see _eo_id_mem_alloc */
-#define MAX_MID_TABLE_ID (1 << BITS_MID_TABLE_ID)
-#define MAX_TABLE_ID ((1 << BITS_TABLE_ID) - DROPPED_TABLES )
-#define MAX_ENTRY_ID ((1 << BITS_ENTRY_ID) - DROPPED_ENTRIES)
-#define MAX_GENERATIONS (1 << BITS_GENERATION_COUNTER)
-
-/* Masks */
-#define MASK_MID_TABLE_ID (MAX_MID_TABLE_ID - 1)
-#define MASK_TABLE_ID ((1 << BITS_TABLE_ID) - 1)
-#define MASK_ENTRY_ID ((1 << BITS_ENTRY_ID) - 1)
-#define MASK_GENERATIONS (MAX_GENERATIONS - 1)
-
-#define MEM_HEADER_SIZE 16
-#define MEM_PAGE_SIZE 4096
-#define MEM_MAGIC 0x3f61ec8a
-
-typedef struct _Mem_Header
-{
- size_t size;
- size_t magic;
-} Mem_Header;
-
-static void *
-_eo_id_mem_alloc(size_t size)
-{
-#ifdef __linux__
- void *ptr;
- Mem_Header *hdr;
- size_t newsize;
- newsize = MEM_PAGE_SIZE * ((size + MEM_HEADER_SIZE + MEM_PAGE_SIZE - 1) /
- MEM_PAGE_SIZE);
- ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (ptr == MAP_FAILED)
- {
- ERR("mmap of eo id table region failed!");
- return NULL;
- }
- hdr = ptr;
- hdr->size = newsize;
- hdr->magic = MEM_MAGIC;
- /* DBG("asked:%lu allocated:%lu wasted:%lu bytes", size, newsize, (newsize
- size)); */
- return (void *)(((unsigned char *)ptr) + MEM_HEADER_SIZE);
-#else
- return malloc(size);
-#endif
-}
-
-static void *
-_eo_id_mem_calloc(size_t num, size_t size)
-{
- void *ptr = _eo_id_mem_alloc(num * size);
- if (!ptr) return NULL;
- memset(ptr, 0, num * size);
- return ptr;
-}
-
-static void
-_eo_id_mem_free(void *ptr)
-{
-#ifdef __linux__
- Mem_Header *hdr;
- if (!ptr) return;
- hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
- if (hdr->magic != MEM_MAGIC)
- {
- ERR("unmap of eo table region has bad magic!");
- return;
- }
- munmap(hdr, hdr->size);
-#else
- free(ptr);
-#endif
-}
-
-#ifdef EINA_DEBUG_MALLOC
-static void
-_eo_id_mem_protect(void *ptr, Eina_Bool may_not_write)
-{
-# ifdef __linux__
- Mem_Header *hdr;
- if (!ptr) return;
- hdr = (Mem_Header *)(((unsigned char *)ptr) - MEM_HEADER_SIZE);
- if (hdr->magic != MEM_MAGIC)
- {
- ERR("mprotect of eo table region has bad magic!");
- return;
- }
- mprotect(hdr, hdr->size, PROT_READ | ( may_not_write ? 0 : PROT_WRITE) );
-# endif
-}
-# define PROTECT(_ptr_) _eo_id_mem_protect((_ptr_), EINA_TRUE)
-# define UNPROTECT(_ptr_) _eo_id_mem_protect((_ptr_), EINA_FALSE)
-#else
-# define PROTECT(_ptr_)
-# define UNPROTECT(_ptr_)
-#endif
-
-/* Entry */
-typedef struct
-{
- /* Pointer to the object */
- _Eo *ptr;
- /* Indicates where to find the next entry to recycle */
- Table_Index next_in_fifo;
- /* Active flag */
- unsigned int active : 1;
- /* Generation */
- unsigned int generation : BITS_GENERATION_COUNTER;
-
-} _Eo_Id_Entry;
-
-/* Table */
-typedef struct
-{
- /* Indicates where start the "never used" entries */
- Table_Index start;
- /* Indicates where to find the next entry to recycle */
- Table_Index fifo_head;
- /* Indicates where to add an entry to recycle */
- Table_Index fifo_tail;
- /* Packed mid table and table indexes */
- Eo_Id partial_id;
- /* Counter of free entries */
- unsigned int free_entries;
- /* Entries of the table holding real pointers and generations */
- _Eo_Id_Entry entries[MAX_ENTRY_ID];
-} _Eo_Ids_Table;
/* Tables handling pointers indirection */
-static _Eo_Ids_Table **_eo_ids_tables[MAX_MID_TABLE_ID] = { NULL };
+_Eo_Ids_Table **_eo_ids_tables[MAX_MID_TABLE_ID] = { NULL };
/* Current table used for following allocations */
-static _Eo_Ids_Table *_current_table = NULL;
+_Eo_Ids_Table *_current_table = NULL;
/* Spare empty table */
-static _Eo_Ids_Table *_empty_table = NULL;
+_Eo_Ids_Table *_empty_table = NULL;
/* Next generation to use when assigning a new entry to a Eo pointer */
Generation_Counter _eo_generation_counter = 0;
-
-/* Macro used to compose an Eo id */
-#define EO_COMPOSE_PARTIAL_ID(MID_TABLE, TABLE) \
- (((Eo_Id)(MID_TABLE & MASK_MID_TABLE_ID) << SHIFT_MID_TABLE_ID) | \
- ((Eo_Id)(TABLE & MASK_TABLE_ID) << SHIFT_TABLE_ID))
-
-#define EO_COMPOSE_FINAL_ID(PARTIAL_ID, ENTRY, GENERATION) \
- (PARTIAL_ID | \
- ((ENTRY & MASK_ENTRY_ID) << SHIFT_ENTRY_ID) | \
- (GENERATION & MASK_GENERATIONS ))
-
-/* Macro to extract from an Eo id the indexes of the tables */
-#define EO_DECOMPOSE_ID(ID, MID_TABLE, TABLE, ENTRY, GENERATION) \
- MID_TABLE = (ID >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID; \
- TABLE = (ID >> SHIFT_TABLE_ID) & MASK_TABLE_ID; \
- ENTRY = (ID >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID; \
- GENERATION = ID & MASK_GENERATIONS;
-
-/* Macro used for readability */
-#define TABLE_FROM_IDS _eo_ids_tables[mid_table_id][table_id]
-
-_Eo *
-_eo_obj_pointer_get(const Eo_Id obj_id)
-{
-#ifdef HAVE_EO_ID
- _Eo_Id_Entry *entry;
- Generation_Counter generation;
- Table_Index mid_table_id, table_id, entry_id;
-
- EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
-
- /* Check the validity of the entry */
- if (_eo_ids_tables[mid_table_id] && TABLE_FROM_IDS)
- {
- entry = &(TABLE_FROM_IDS->entries[entry_id]);
- if (entry && entry->active && (entry->generation == generation))
- return entry->ptr;
- }
-
- ERR("obj_id %p is not pointing to a valid object. Maybe it has already been
freed.",
- (void *)obj_id);
-
- return NULL;
-#else
- return (_Eo *)obj_id;
-#endif
-}
-
-static inline _Eo_Id_Entry *
-_get_available_entry(_Eo_Ids_Table *table)
-{
- _Eo_Id_Entry *entry = NULL;
-
- if (table->start != MAX_ENTRY_ID)
- {
- /* Serve never used entries first */
- entry = &(table->entries[table->start]);
- UNPROTECT(table);
- table->start++;
- table->free_entries--;
- }
- else if (table->fifo_head != -1)
- {
- /* Pop a free entry from the fifo */
- entry = &(table->entries[table->fifo_head]);
- UNPROTECT(table);
- if (entry->next_in_fifo == -1)
- table->fifo_head = table->fifo_tail = -1;
- else
- table->fifo_head = entry->next_in_fifo;
- table->free_entries--;
- }
-
- return entry;
-}
-
-static inline _Eo_Id_Entry *
-_search_tables()
-{
- _Eo_Ids_Table *table;
- _Eo_Id_Entry *entry;
-
- for (Table_Index mid_table_id = 0; mid_table_id < MAX_MID_TABLE_ID;
mid_table_id++)
- {
- if (!_eo_ids_tables[mid_table_id])
- {
- /* Allocate a new intermediate table */
- _eo_ids_tables[mid_table_id] = _eo_id_mem_calloc(MAX_TABLE_ID,
sizeof(_Eo_Ids_Table*));
- }
-
- for (Table_Index table_id = 0; table_id < MAX_TABLE_ID; table_id++)
- {
- table = TABLE_FROM_IDS;
-
- if (!table)
- {
- if (_empty_table)
- {
- /* Recycle the available empty table */
- table = _empty_table;
- _empty_table = NULL;
- UNPROTECT(table);
- }
- else
- {
- /* Allocate a new table */
- table = _eo_id_mem_calloc(1, sizeof(_Eo_Ids_Table));
- }
- /* Initialize the table and reserve the first entry */
- table->start = 1;
- table->free_entries = MAX_ENTRY_ID - 1;
- table->fifo_head = table->fifo_tail = -1;
- table->partial_id = EO_COMPOSE_PARTIAL_ID(mid_table_id,
table_id);
- entry = &(table->entries[0]);
- UNPROTECT(_eo_ids_tables[mid_table_id]);
- TABLE_FROM_IDS = table;
- PROTECT(_eo_ids_tables[mid_table_id]);
- }
- else
- entry = _get_available_entry(table);
-
- if (entry)
- {
- /* Store table info into current table */
- _current_table = table;
- return entry;
- }
- }
- }
-
- ERR("no more available entries to store eo objects");
- _current_table = NULL;
- return NULL;
-}
-
-Eo_Id
-_eo_id_allocate(const _Eo *obj)
-{
-#ifdef HAVE_EO_ID
- _Eo_Id_Entry *entry = NULL;
-
- if (_current_table)
- entry = _get_available_entry(_current_table);
-
- if (!entry)
- {
- entry = _search_tables();
- if (!entry)
- return 0;
- }
-
- /* [1;max-1] thus we never generate an Eo_Id equal to 0 */
- _eo_generation_counter++;
- if (_eo_generation_counter == MAX_GENERATIONS)
- _eo_generation_counter = 1;
- /* Fill the entry and return it's Eo Id */
- entry->ptr = (_Eo *)obj;
- entry->active = 1;
- entry->generation = _eo_generation_counter;
- PROTECT(_current_table);
- return EO_COMPOSE_FINAL_ID(_current_table->partial_id,
- (entry - _current_table->entries),
- entry->generation);
-#else
- return (Eo_Id)obj;
-#endif
-}
-
-void
-_eo_id_release(const Eo_Id obj_id)
-{
-#ifdef HAVE_EO_ID
- _Eo_Ids_Table *table;
- _Eo_Id_Entry *entry;
- Generation_Counter generation;
- Table_Index mid_table_id, table_id, entry_id;
- EO_DECOMPOSE_ID(obj_id, mid_table_id, table_id, entry_id, generation);
-
- /* Check the validity of the entry */
- if (_eo_ids_tables[mid_table_id] && (table = TABLE_FROM_IDS))
- {
- entry = &(table->entries[entry_id]);
- if (entry && entry->active && (entry->generation == generation))
- {
- UNPROTECT(table);
- table->free_entries++;
- /* Disable the entry */
- entry->active = 0;
- entry->next_in_fifo = -1;
- /* Push the entry into the fifo */
- if (table->fifo_tail == -1)
- {
- table->fifo_head = table->fifo_tail = entry_id;
- }
- else
- {
- table->entries[table->fifo_tail].next_in_fifo = entry_id;
- table->fifo_tail = entry_id;
- }
- PROTECT(table);
- if (table->free_entries == MAX_ENTRY_ID)
- {
- UNPROTECT(_eo_ids_tables[mid_table_id]);
- TABLE_FROM_IDS = NULL;
- PROTECT(_eo_ids_tables[mid_table_id]);
- /* Recycle or free the empty table */
- if (!_empty_table)
- _empty_table = table;
- else
- _eo_id_mem_free(table);
- if (_current_table == table)
- _current_table = NULL;
- }
- return;
- }
- }
-
- ERR("obj_id %p is not pointing to a valid object. Maybe it has already been
freed.", (void *)obj_id);
-#else
- (void) obj_id;
-#endif
-}
-
-void
-_eo_free_ids_tables()
-{
- for (Table_Index mid_table_id = 0; mid_table_id < MAX_MID_TABLE_ID;
mid_table_id++)
- {
- if (_eo_ids_tables[mid_table_id])
- {
- for (Table_Index table_id = 0; table_id < MAX_TABLE_ID;
table_id++)
- {
- if (TABLE_FROM_IDS)
- {
- _eo_id_mem_free(TABLE_FROM_IDS);
- }
- }
- _eo_id_mem_free(_eo_ids_tables[mid_table_id]);
- }
- _eo_ids_tables[mid_table_id] = NULL;
- }
- if (_empty_table) _eo_id_mem_free(_empty_table);
- _empty_table = _current_table = NULL;
-}
-
-#ifdef EFL_DEBUG
-void
-_eo_print()
-{
- _Eo_Id_Entry *entry;
- unsigned long obj_number = 0;
- for (Table_Index mid_table_id = 0; mid_table_id < MAX_MID_TABLE_ID;
mid_table_id++)
- {
- if (_eo_ids_tables[mid_table_id])
- {
- for (Table_Index table_id = 0; table_id < MAX_TABLE_ID;
table_id++)
- {
- if (TABLE_FROM_IDS)
- {
- for (Table_Index entry_id = 0; entry_id < MAX_ENTRY_ID;
entry_id++)
- {
- entry = &(TABLE_FROM_IDS->entries[entry_id]);
- if (entry->active)
- {
- printf("%ld: %p -> (%p, %p, %p, %p)\n",
obj_number++,
- entry->ptr,
- (void *)mid_table_id, (void *)table_id,
(void *)entry_id,
- (void *)entry->generation);
- }
- }
- }
- }
- }
- }
-}
-#endif
diff --git a/src/lib/eo/eo_ptr_indirection.h b/src/lib/eo/eo_ptr_indirection.h
index c8f4e9c..cb890e7 100644
--- a/src/lib/eo/eo_ptr_indirection.h
+++ b/src/lib/eo/eo_ptr_indirection.h
@@ -44,5 +44,7 @@
void _eo_print();
#endif
+#include "eo_ptr_indirection.x"
+
#endif
diff --git a/src/lib/eo/eo_ptr_indirection.c b/src/lib/eo/eo_ptr_indirection.x
similarity index 97%
copy from src/lib/eo/eo_ptr_indirection.c
copy to src/lib/eo/eo_ptr_indirection.x
index 3bb28c1..3bec84f 100644
--- a/src/lib/eo/eo_ptr_indirection.c
+++ b/src/lib/eo/eo_ptr_indirection.x
@@ -1,8 +1,3 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "eo_ptr_indirection.h"
#include <assert.h>
#ifdef __linux__
#include <sys/types.h>
@@ -221,16 +216,16 @@ typedef struct
} _Eo_Ids_Table;
/* Tables handling pointers indirection */
-static _Eo_Ids_Table **_eo_ids_tables[MAX_MID_TABLE_ID] = { NULL };
+extern _Eo_Ids_Table **_eo_ids_tables[MAX_MID_TABLE_ID];
/* Current table used for following allocations */
-static _Eo_Ids_Table *_current_table = NULL;
+extern _Eo_Ids_Table *_current_table;
/* Spare empty table */
-static _Eo_Ids_Table *_empty_table = NULL;
+extern _Eo_Ids_Table *_empty_table;
/* Next generation to use when assigning a new entry to a Eo pointer */
-Generation_Counter _eo_generation_counter = 0;
+extern Generation_Counter _eo_generation_counter;
/* Macro used to compose an Eo id */
#define EO_COMPOSE_PARTIAL_ID(MID_TABLE, TABLE) \
@@ -252,7 +247,7 @@ Generation_Counter _eo_generation_counter = 0;
/* Macro used for readability */
#define TABLE_FROM_IDS _eo_ids_tables[mid_table_id][table_id]
-_Eo *
+static inline _Eo *
_eo_obj_pointer_get(const Eo_Id obj_id)
{
#ifdef HAVE_EO_ID
@@ -308,7 +303,7 @@ _get_available_entry(_Eo_Ids_Table *table)
}
static inline _Eo_Id_Entry *
-_search_tables()
+_search_tables(void)
{
_Eo_Ids_Table *table;
_Eo_Id_Entry *entry;
@@ -366,7 +361,7 @@ _search_tables()
return NULL;
}
-Eo_Id
+static inline Eo_Id
_eo_id_allocate(const _Eo *obj)
{
#ifdef HAVE_EO_ID
@@ -399,7 +394,7 @@ _eo_id_allocate(const _Eo *obj)
#endif
}
-void
+static inline void
_eo_id_release(const Eo_Id obj_id)
{
#ifdef HAVE_EO_ID
@@ -454,8 +449,8 @@ _eo_id_release(const Eo_Id obj_id)
#endif
}
-void
-_eo_free_ids_tables()
+static inline void
+_eo_free_ids_tables(void)
{
for (Table_Index mid_table_id = 0; mid_table_id < MAX_MID_TABLE_ID;
mid_table_id++)
{
@@ -477,8 +472,8 @@ _eo_free_ids_tables()
}
#ifdef EFL_DEBUG
-void
-_eo_print()
+static inline void
+_eo_print(void)
{
_Eo_Id_Entry *entry;
unsigned long obj_number = 0;
--
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev