From: Mike McCormack <mj.mccormack@samsung.com>

Subject: [E-devel] [PATCH] ecore main loop "fd_handlers_to_call" list optimization
Date: Thu, 02 Dec 2010 15:22:13 +0900

Hi All,

Rather than using malloc'ed list entries in the mail loop, use a single linked in-place list.

This avoid lots of mallocs and frees as the main loop iterates.

thanks,

Mike


SVN revision: 56368
This commit is contained in:
Mike McCormack 2011-01-29 05:34:00 +00:00 committed by Mike Blumenkrantz
parent 7d8b4f6f68
commit 56b1e2dcc4
1 changed files with 64 additions and 53 deletions

View File

@ -61,6 +61,7 @@ struct _Ecore_Fd_Handler
{ {
EINA_INLIST; EINA_INLIST;
ECORE_MAGIC; ECORE_MAGIC;
Ecore_Fd_Handler *next_ready;
int fd; int fd;
Ecore_Fd_Handler_Flags flags; Ecore_Fd_Handler_Flags flags;
Ecore_Fd_Cb func; Ecore_Fd_Cb func;
@ -119,9 +120,9 @@ static Eina_List *fd_handlers_with_prep = NULL;
static Eina_List *fd_handlers_with_buffer = NULL; static Eina_List *fd_handlers_with_buffer = NULL;
static Eina_List *fd_handlers_to_delete = NULL; static Eina_List *fd_handlers_to_delete = NULL;
static Eina_List *fd_handlers_to_call = NULL; /* single linked list of ready fdhs, terminated by loop to self */
static Eina_List *fd_handlers_to_call_current; static Ecore_Fd_Handler *fd_handlers_to_call;
static Eina_List *fd_handlers_to_call_current_next; static Ecore_Fd_Handler *fd_handlers_to_call_current;
#ifdef _WIN32 #ifdef _WIN32
static Ecore_Win32_Handler *win32_handlers = NULL; static Ecore_Win32_Handler *win32_handlers = NULL;
@ -166,6 +167,24 @@ _ecore_fd_valid(void)
#endif #endif
} }
static inline void
_ecore_try_add_to_call_list(Ecore_Fd_Handler *fdh)
{
/* check if this fdh is already in the list */
if (fdh->next_ready)
return;
if (fdh->read_active || fdh->write_active || fdh->error_active)
{
/*
* make sure next_ready is non-null by pointing to ourselves
* use that to indicate this fdh is in the ready list
* insert at the head of the list to avoid trouble
*/
fdh->next_ready = fd_handlers_to_call ? fd_handlers_to_call : fdh;
fd_handlers_to_call = fdh;
}
}
#ifdef HAVE_EPOLL #ifdef HAVE_EPOLL
static inline int static inline int
_ecore_get_epoll_fd(void) _ecore_get_epoll_fd(void)
@ -332,7 +351,6 @@ static inline int _ecore_main_fdh_poll_mark_active(void)
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
{ {
Ecore_Fd_Handler *fdh; Ecore_Fd_Handler *fdh;
Eina_Bool pst, st;
fdh = ev[i].data.ptr; fdh = ev[i].data.ptr;
if (!ECORE_MAGIC_CHECK(fdh, ECORE_MAGIC_FD_HANDLER)) if (!ECORE_MAGIC_CHECK(fdh, ECORE_MAGIC_FD_HANDLER))
@ -346,15 +364,15 @@ static inline int _ecore_main_fdh_poll_mark_active(void)
ERR("deleted fd in epoll"); ERR("deleted fd in epoll");
continue; continue;
} }
pst = st = fdh->read_active | fdh->write_active | fdh->error_active;
if ((ev[i].events & EPOLLIN) && (!fdh->read_active)) if (ev[i].events & EPOLLIN)
st = fdh->read_active = EINA_TRUE; fdh->read_active = EINA_TRUE;
if ((ev[i].events & EPOLLOUT) && (!fdh->write_active)) if (ev[i].events & EPOLLOUT)
st = fdh->write_active = EINA_TRUE; fdh->write_active = EINA_TRUE;
if ((ev[i].events & EPOLLERR) && (!fdh->error_active)) if (ev[i].events & EPOLLERR)
st = fdh->error_active = EINA_TRUE; fdh->error_active = EINA_TRUE;
if (pst != st)
fd_handlers_to_call = eina_list_append(fd_handlers_to_call, fdh); _ecore_try_add_to_call_list(fdh);
} }
return ret; return ret;
@ -365,7 +383,6 @@ static inline int _ecore_main_fdh_poll_mark_active(void)
static inline int _ecore_main_fdh_poll_mark_active(void) static inline int _ecore_main_fdh_poll_mark_active(void)
{ {
Ecore_Fd_Handler *fdh; Ecore_Fd_Handler *fdh;
Eina_Bool pst, st;
int ret = 0; int ret = 0;
/* call the prepare callback for all handlers */ /* call the prepare callback for all handlers */
@ -374,15 +391,15 @@ static inline int _ecore_main_fdh_poll_mark_active(void)
if (fdh->delete_me) if (fdh->delete_me)
continue; continue;
pst = st = fdh->read_active | fdh->write_active | fdh->error_active; if (fdh->gfd.revents & G_IO_IN)
if ((fdh->gfd.revents & G_IO_IN) && (!fdh->read_active)) fdh->read_active = EINA_TRUE;
st = fdh->read_active = EINA_TRUE; if (fdh->gfd.revents & G_IO_OUT)
if ((fdh->gfd.revents & G_IO_OUT) && (!fdh->write_active)) fdh->write_active = EINA_TRUE;
st = fdh->write_active = EINA_TRUE; if (fdh->gfd.revents & G_IO_ERR)
if ((fdh->gfd.revents & G_IO_ERR) && (!fdh->error_active)) fdh->error_active = EINA_TRUE;
st = fdh->error_active = EINA_TRUE;
if (pst != st) _ecore_try_add_to_call_list(fdh);
fd_handlers_to_call = eina_list_append(fd_handlers_to_call, fdh);
if (fdh->gfd.revents & (G_IO_IN|G_IO_OUT|G_IO_ERR)) ret++; if (fdh->gfd.revents & (G_IO_IN|G_IO_OUT|G_IO_ERR)) ret++;
} }
@ -763,6 +780,7 @@ ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func
fdh = calloc(1, sizeof(Ecore_Fd_Handler)); fdh = calloc(1, sizeof(Ecore_Fd_Handler));
if (!fdh) return NULL; if (!fdh) return NULL;
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER); ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
fdh->next_ready = NULL;
fdh->fd = fd; fdh->fd = fd;
fdh->flags = flags; fdh->flags = flags;
if (_ecore_main_fdh_poll_add(fdh) < 0) if (_ecore_main_fdh_poll_add(fdh) < 0)
@ -999,9 +1017,8 @@ _ecore_main_shutdown(void)
fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep); fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep);
if (fd_handlers_to_delete) if (fd_handlers_to_delete)
fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete); fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete);
if (fd_handlers_to_call)
fd_handlers_to_call = eina_list_free(fd_handlers_to_call);
fd_handlers_to_call = NULL;
fd_handlers_to_call_current = NULL; fd_handlers_to_call_current = NULL;
fd_handlers_to_delete = NULL; fd_handlers_to_delete = NULL;
fd_handler_current = NULL; fd_handler_current = NULL;
@ -1140,16 +1157,13 @@ _ecore_main_select(double timeout)
{ {
if (!fdh->delete_me) if (!fdh->delete_me)
{ {
Eina_Bool pst, st; if (FD_ISSET(fdh->fd, &rfds))
pst = st = fdh->read_active | fdh->write_active | fdh->error_active; fdh->read_active = EINA_TRUE;
if ((FD_ISSET(fdh->fd, &rfds)) && (!fdh->read_active)) if (FD_ISSET(fdh->fd, &wfds))
st = fdh->read_active = EINA_TRUE; fdh->write_active = EINA_TRUE;
if ((FD_ISSET(fdh->fd, &wfds)) && (!fdh->write_active)) if (FD_ISSET(fdh->fd, &exfds))
st = fdh->write_active = EINA_TRUE; fdh->error_active = EINA_TRUE;
if ((FD_ISSET(fdh->fd, &exfds)) && (!fdh->error_active)) _ecore_try_add_to_call_list(fdh);
st = fdh->error_active = EINA_TRUE;
if (pst != st)
fd_handlers_to_call = eina_list_append(fd_handlers_to_call, fdh);
} }
} }
#endif /* HAVE_EPOLL */ #endif /* HAVE_EPOLL */
@ -1286,22 +1300,16 @@ _ecore_main_win32_handlers_cleanup(void)
static void static void
_ecore_main_fd_handlers_call(void) _ecore_main_fd_handlers_call(void)
{ {
/* grab a new list */
if (!fd_handlers_to_call_current) if (!fd_handlers_to_call_current)
{ {
/* regular main loop, start from head */
fd_handlers_to_call_current = fd_handlers_to_call; fd_handlers_to_call_current = fd_handlers_to_call;
fd_handlers_to_call_current_next = eina_list_next(fd_handlers_to_call_current); fd_handlers_to_call = NULL;
}
else
{
/* recursive main loop, continue from where we were */
fd_handlers_to_call_current = fd_handlers_to_call_current_next;
fd_handlers_to_call_current_next = eina_list_next(fd_handlers_to_call_current);
} }
while (fd_handlers_to_call_current) while (fd_handlers_to_call_current)
{ {
Ecore_Fd_Handler *fdh = fd_handlers_to_call_current->data; Ecore_Fd_Handler *fdh = fd_handlers_to_call_current;
if (!fdh->delete_me) if (!fdh->delete_me)
{ {
@ -1328,9 +1336,16 @@ _ecore_main_fd_handlers_call(void)
} }
} }
fd_handlers_to_call = eina_list_remove_list(fd_handlers_to_call, fd_handlers_to_call_current); /* stop when we point to ourselves */
fd_handlers_to_call_current = fd_handlers_to_call_current_next; if (fdh->next_ready == fdh)
fd_handlers_to_call_current_next = eina_list_next(fd_handlers_to_call_current_next); {
fdh->next_ready = NULL;
fd_handlers_to_call_current = NULL;
break;
}
fd_handlers_to_call_current = fdh->next_ready;
fdh->next_ready = NULL;
} }
} }
@ -1355,12 +1370,8 @@ _ecore_main_fd_handlers_buf_call(void)
if (fdh->buf_func(fdh->buf_data, fdh)) if (fdh->buf_func(fdh->buf_data, fdh))
{ {
ret |= fdh->func(fdh->data, fdh); ret |= fdh->func(fdh->data, fdh);
if (!fdh->read_active) fdh->read_active = EINA_TRUE;
{ _ecore_try_add_to_call_list(fdh);
fdh->read_active = EINA_TRUE;
if ((!fdh->write_active) && (!fdh->error_active))
fd_handlers_to_call = eina_list_append(fd_handlers_to_call, fdh);
}
} }
fdh->references--; fdh->references--;
} }