ws2_32: Cache the memory used for poll() calls

Bruno Jesus 00cpxxx at gmail.com
Fri May 23 22:14:20 CDT 2014


I have been testing some applications that rely heavily on the
select(), recv() and send() calls. After the recent work in send/recv
the program got improved but there is still an issue with calling
select() thousands of times with 192 sockets set in the fdsets (64 per
fdset). Caching the memory used by poll (used in the wine select call)
helps improving the performance of the application a bit and I see no
drawbacks of doing so. 64 descriptors means only 512 bytes of cached
memory.
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index e31f396..6832117 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -389,6 +389,8 @@ struct per_thread_data
     struct WS_hostent *he_buffer;
     struct WS_servent *se_buffer;
     struct WS_protoent *pe_buffer;
+    struct pollfd *fd_cache;
+    unsigned int fd_count;
     int he_len;
     int se_len;
     int pe_len;
@@ -937,6 +939,7 @@ static void free_per_thread_data(void)
     HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
     HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
     HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
+    HeapFree( GetProcessHeap(), 0, ptb->fd_cache );
     ptb->he_buffer = NULL;
     ptb->se_buffer = NULL;
     ptb->pe_buffer = NULL;
@@ -4286,6 +4289,7 @@ static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set
 {
     unsigned int i, j = 0, count = 0;
     struct pollfd *fds;
+    struct per_thread_data *ptb = get_per_thread_data();
 
     if (readfds) count += readfds->fd_count;
     if (writefds) count += writefds->fd_count;
@@ -4296,11 +4300,21 @@ static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set
         SetLastError(WSAEINVAL);
         return NULL;
     }
-    if (!(fds = HeapAlloc( GetProcessHeap(), 0, count * sizeof(fds[0]))))
+    /* check if the cache can hold all descriptors, if not do the resizing */
+    if (ptb->fd_count < count)
     {
-        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
-        return NULL;
+        if (!(fds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(fds[0]))))
+        {
+            SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+            return NULL;
+        }
+        HeapFree(GetProcessHeap(), 0, ptb->fd_cache);
+        ptb->fd_cache = fds;
+        ptb->fd_count = count;
     }
+    else
+        fds = ptb->fd_cache;
+
     if (readfds)
         for (i = 0; i < readfds->fd_count; i++, j++)
         {
@@ -4339,7 +4353,6 @@ failed:
     if (exceptfds)
         for (i = 0; i < exceptfds->fd_count && j < count; i++, j++)
             release_sock_fd( exceptfds->fd_array[i], fds[j].fd );
-    HeapFree( GetProcessHeap(), 0, fds );
     return NULL;
 }
 
@@ -4452,7 +4465,6 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
 
     if (ret == -1) SetLastError(wsaErrno());
     else ret = get_poll_results( ws_readfds, ws_writefds, ws_exceptfds, pollfds );
-    HeapFree( GetProcessHeap(), 0, pollfds );
     return ret;
 }
 


More information about the wine-patches mailing list