View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001735 | GNUnet | util library | public | 2011-07-13 02:12 | 2011-07-18 19:56 |
Reporter | LRN | Assigned To | LRN | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Product Version | Git master | ||||
Summary | 0001735: Introduce adaptive poll cycle length in GNUNET_NETWORK_socket_select () | ||||
Description | This patch uses variable select()/sleep() timeout instead of fixing it at 100000 microseconds. Timeout starts at 20 microseconds. Timeout is multiplied by 1.4 every time the cycle selects nothing (select() returns 0 on sockets, and polling pipes yields nothing). Timeout is decreased by 2 microseconds every time the cycle selects something (either select() detects a socket state change, or pipe polling detects a pipe state change). | ||||
Tags | No tags attached. | ||||
Attached Files | 0001-Use-adaptive-cycle-delay-in-w32-select.patch (2,934 bytes)
From c3aafd522486c12776db69ac301d77f730291e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?= =?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com> Date: Wed, 13 Jul 2011 04:07:04 +0400 Subject: [PATCH] Use adaptive cycle delay in w32 select() --- src/util/network.c | 34 +++++++++++++++++++++++++++++++--- 1 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/util/network.c b/src/util/network.c index 726e295..48bd863 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -29,7 +29,9 @@ #include "disk.h" #include "gnunet_container_lib.h" -#define DEBUG_NETWORK GNUNET_YES +#define DEBUG_NETWORK GNUNET_NO + +#define DEBUG_W32_CYCLES GNUNET_NO #ifndef INVALID_SOCKET #define INVALID_SOCKET -1 @@ -1106,6 +1108,8 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, struct timeval tvslice; int retcode; DWORD ms_total; + /* Number of milliseconds per cycle. Adapted on the fly */ + static unsigned int cycle_delay = 20; #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) @@ -1145,6 +1149,12 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, FD_ZERO (&aread); FD_ZERO (&awrite); FD_ZERO (&aexcept); + +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting a cycle, delay is %dms\n", cycle_delay); +#endif + limit = GetTickCount () + ms_total; do @@ -1160,7 +1170,7 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, FD_COPY (&sock_write, &awrite); FD_COPY (&sock_except, &aexcept); tvslice.tv_sec = 0; - tvslice.tv_usec = 100000; + tvslice.tv_usec = cycle_delay; if ((retcode = select (nfds + 1, &aread, &awrite, &aexcept, &tvslice)) == SOCKET_ERROR) @@ -1301,8 +1311,26 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, } } select_loop_end: + if (retcode == 0) + { + /* Missed an I/O - double the cycle time */ + cycle_delay = cycle_delay * 2 > 250 ? 250 : cycle_delay * 1.4; +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "The cycle missed, increased the delay to %dms\n", cycle_delay); +#endif + } + else + { + /* Successfully selected something - decrease the cycle time */ + cycle_delay -= cycle_delay > 2 ? 2 : 0; +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "The cycle hit, decreased the delay to %dms\n", cycle_delay); +#endif + } if (retcode == 0 && nfds == 0) - Sleep (GNUNET_MIN (100, limit - GetTickCount ())); + Sleep (GNUNET_MIN (cycle_delay * 1000, limit - GetTickCount ())); } while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit)); -- 1.7.4 0001-Change-the-cycle-timeout-adjustment-for-w32-select.patch (6,342 bytes)
From a37445b81ca9ad088bacca7064c021016a2a2ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?= =?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com> Date: Mon, 18 Jul 2011 20:47:46 +0400 Subject: [PATCH] Change the cycle timeout adjustment for w32 select --- src/util/network.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/util/network.c b/src/util/network.c index bef285b..6a74535 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -1152,7 +1152,7 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, #if DEBUG_W32_CYCLES GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting a cycle, delay is %dms\n", cycle_delay); + "Starting a cycle, delay is %dms. nfds is %d.\n", cycle_delay, nfds); #endif limit = GetTickCount () + ms_total; @@ -1171,6 +1171,30 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, FD_COPY (&sock_except, &aexcept); tvslice.tv_sec = 0; tvslice.tv_usec = cycle_delay; +#if DEBUG_W32_CYCLES + { + for (i = 0; i < nfds; i++) + { + if (SAFE_FD_ISSET (i, &sock_read)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Going to select socket %d for reading\n", i); + } + if (SAFE_FD_ISSET (i, &sock_write)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Going to select socket %d for writing\n", i); + } + if (SAFE_FD_ISSET (i, &sock_except)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Going to select socket %d for exceptions\n", i); + } + } + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Waiting for %d microseconds, %d left\n", cycle_delay, (limit - GetTickCount ())*1000); +#endif if ((retcode = select (nfds + 1, &aread, &awrite, &aexcept, &tvslice)) == SOCKET_ERROR) @@ -1186,13 +1210,20 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, #endif goto select_loop_end; } +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Select () returned %d, GLE is %d\n", retcode, GetLastError ()); +#endif } /* Poll read pipes */ if (rfds) - { struct GNUNET_CONTAINER_SList_Iterator *i; +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Polling rfds for readable pipes\n"); +#endif for (i = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (i) != GNUNET_YES; GNUNET_CONTAINER_slist_next (i)) @@ -1203,6 +1234,10 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); if (fh->type == GNUNET_PIPE) { +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Polling pipe 0x%x (0x%x)\n", fh, fh->h); +#endif if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) { DWORD error_code = GetLastError (); @@ -1250,6 +1285,10 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, if (efds) { +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Polling efds for broken pipes\n"); +#endif struct GNUNET_CONTAINER_SList_Iterator *i; for (i = GNUNET_CONTAINER_slist_begin (efds->handles); GNUNET_CONTAINER_slist_end (i) != GNUNET_YES; @@ -1262,6 +1301,10 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); if (fh->type == GNUNET_PIPE) { +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Polling pipe 0x%x (0x%x)\n", fh, fh->h); +#endif if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) { @@ -1313,8 +1356,13 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, select_loop_end: if (retcode == 0) { + /* For pipes, there have been no select() call, so the poll is + * more likely to miss first time around. For now just don't increase + * the delay for pipes only. + */ + if (nfds != 0) + cycle_delay = cycle_delay * 2 > 250000 ? 250000 : cycle_delay * 1.4; /* Missed an I/O - double the cycle time */ - cycle_delay = cycle_delay * 2 > 250 ? 250 : cycle_delay * 1.4; #if DEBUG_W32_CYCLES GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The cycle missed, increased the delay to %dms\n", cycle_delay); @@ -1323,14 +1371,25 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, else { /* Successfully selected something - decrease the cycle time */ - cycle_delay -= cycle_delay > 2 ? 2 : 0; + /* Minimum is 5 microseconds. Decrease the delay by half, + * or by 5000 - whichever is higher. + */ + cycle_delay -= cycle_delay > 5000 ? GNUNET_MAX (5000, cycle_delay / 2) : cycle_delay - 5; #if DEBUG_W32_CYCLES GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The cycle hit, decreased the delay to %dms\n", cycle_delay); #endif } if (retcode == 0 && nfds == 0) - Sleep (GNUNET_MIN (cycle_delay * 1000, limit - GetTickCount ())); + { + long long diff = limit - GetTickCount (); + diff = diff > 0 ? diff : 0; +#if DEBUG_W32_CYCLES + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No sockets, sleeping for %d or %d ms\n", cycle_delay / 1000, diff); +#endif + Sleep (GNUNET_MIN (cycle_delay / 1000, diff)); + } } while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit)); -- 1.7.4 | ||||
|
Committed as revision 15963. |
|
Reopened to add another patch. |
|
Added a patch that adjusts the delay. 1) Correctly uses microseconds, because select() takes timeout value in microseconds, so the code that is in current SVN HEAD actually times out after 250 _microseconds_ tops - obviously, that's a bit low. 2) Won't adjust the delay when poll misses on pipes and there are no sockets in fd_sets. Because pipes are checked first, and only then waited upon, it is not appropriate to count this against the the cycle length. 3) Delay adjustment code is made more aggressive towards decreasing the delay: It will cut it by half or by 5000 microseconds (whichever is higher) on every hit, while increasing it only by 1.4 times on every miss. This allows for the usual (fast) performance on transport tests (previous, unpublished, versions of this patch were stuck at 250000 microseconds, because misses influenced the delay more than hits did). |
|
That patch does not apply at all against SVN 16080. Can you supply one against SVN HEAD? (I don't even have an easy time finding the respective lines for sure...). |
|
Replaced the patch with the correct version. |
|
Applied as SVN 16097. |
Date Modified | Username | Field | Change |
---|---|---|---|
2011-07-13 02:12 | LRN | New Issue | |
2011-07-13 02:12 | LRN | File Added: 0001-Use-adaptive-cycle-delay-in-w32-select.patch | |
2011-07-14 19:09 | Christian Grothoff | Note Added: 0004503 | |
2011-07-14 19:09 | Christian Grothoff | Status | new => resolved |
2011-07-14 19:09 | Christian Grothoff | Resolution | open => fixed |
2011-07-14 19:09 | Christian Grothoff | Assigned To | => Christian Grothoff |
2011-07-14 19:09 | Christian Grothoff | Assigned To | Christian Grothoff => LRN |
2011-07-15 14:38 | Christian Grothoff | Relationship added | related to 0001620 |
2011-07-18 00:35 | LRN | Note Added: 0004517 | |
2011-07-18 00:35 | LRN | Status | resolved => feedback |
2011-07-18 00:35 | LRN | Resolution | fixed => reopened |
2011-07-18 00:36 | LRN | File Added: 0001-Adjust-adaptive-cycle-delay-logic-a-bit.patch | |
2011-07-18 00:42 | LRN | Note Added: 0004518 | |
2011-07-18 13:32 | Christian Grothoff | Note Added: 0004519 | |
2011-07-18 18:48 | LRN | File Added: 0001-Change-the-cycle-timeout-adjustment-for-w32-select.patch | |
2011-07-18 18:48 | LRN | File Deleted: 0001-Adjust-adaptive-cycle-delay-logic-a-bit.patch | |
2011-07-18 18:48 | LRN | Note Added: 0004526 | |
2011-07-18 19:56 | Christian Grothoff | Note Added: 0004527 | |
2011-07-18 19:56 | Christian Grothoff | Status | feedback => resolved |
2011-07-18 19:56 | Christian Grothoff | Resolution | reopened => fixed |
2011-07-18 19:56 | Christian Grothoff | Status | resolved => closed |