Re: pgbench bug / limitation
| От | Tom Lane |
|---|---|
| Тема | Re: pgbench bug / limitation |
| Дата | |
| Msg-id | 1510961.1591380652@sss.pgh.pa.us обсуждение исходный текст |
| Ответ на | Re: pgbench bug / limitation (Andres Freund <andres@anarazel.de>) |
| Ответы |
Re: pgbench bug / limitation
Re: pgbench bug / limitation |
| Список | pgsql-bugs |
Andres Freund <andres@anarazel.de> writes:
> I'm fairly sure one can easily scale to large numbers of sockets on
> windows by using completion based APIs, but that doesn't seem like a
> realistic thing to use for pgbench anytime soon.
Agreed. Seems like the best answer is to get in bed with the Windows
representation of fd_set, since we cannot avoid knowing that it is
different from other platforms' versions. I suggest that we might as
well get all the way in and dodge the FD_SETSIZE limitation altogether,
as per the attached utterly-untested draft patch.
A remaining problem with this is that in theory, repeatedly applying
socket_has_input() after the wait could also be O(N^2) (unless FD_ISSET
is way smarter than I suspect it is). In practice, that's probably not
a huge problem since there would normally be only a few FDs in the
result fd_set. Still, I'd rather see us get out from under select()
altogether on Windows ... but maybe they *don't* have a better API
anywhere. In any case, this should be a good bit better than what we
have now.
regards, tom lane
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 08a5947a9e..e37f833879 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -27,10 +27,6 @@
*
*/
-#ifdef WIN32
-#define FD_SETSIZE 1024 /* must set before winsock2.h is included */
-#endif
-
#include "postgres_fe.h"
#include <ctype.h>
@@ -51,7 +47,11 @@
#include <poll.h>
#endif
#else /* no ppoll(), so use select() */
+#ifdef WIN32
+#define POLL_USING_WINDOWS_SELECT
+#else
#define POLL_USING_SELECT
+#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -108,6 +108,19 @@ typedef struct socket_set
#endif /* POLL_USING_SELECT */
+#ifdef POLL_USING_WINDOWS_SELECT
+#define SOCKET_WAIT_METHOD "select"
+
+/*----------
+ * On Windows, fd_set is a struct that's effectively
+ * u_int fd_count;
+ * SOCKET fd_array[FLEXIBLE_ARRAY_MEMBER];
+ *----------
+ */
+typedef fd_set socket_set;
+
+#endif /* POLL_USING_WINDOWS_SELECT */
+
/*
* Multi-platform pthread implementations
*/
@@ -6740,6 +6753,70 @@ socket_has_input(socket_set *sa, int fd, int idx)
#endif /* POLL_USING_SELECT */
+#ifdef POLL_USING_WINDOWS_SELECT
+
+static socket_set *
+alloc_socket_set(int count)
+{
+ socket_set *sa;
+
+ sa = (socket_set *) pg_malloc(offsetof(socket_set, fd_array) +
+ sizeof(SOCKET) * count);
+ sa->fd_count = 0;
+ return sa;
+}
+
+static void
+free_socket_set(socket_set *sa)
+{
+ pg_free(sa);
+}
+
+static void
+clear_socket_set(socket_set *sa)
+{
+ FD_ZERO(sa);
+}
+
+static void
+add_socket_to_set(socket_set *sa, int fd, int idx)
+{
+ /*
+ * We do not use FD_SET() here, first because it enforces a maximum array
+ * length of FD_SETSIZE which is not relevant, and second because it
+ * uselessly de-duplicates entries, requiring O(N^2) time to add N FDs to
+ * the set.
+ */
+ Assert(idx == sa->fd_count);
+ sa->fd_array[sa->fd_count++] = fd;
+}
+
+static int
+wait_on_socket_set(socket_set *sa, int64 usecs)
+{
+ if (usecs > 0)
+ {
+ struct timeval timeout;
+
+ timeout.tv_sec = usecs / 1000000;
+ timeout.tv_usec = usecs % 1000000;
+ /* Note that Windows ignores select's first argument */
+ return select(0, sa, NULL, NULL, &timeout);
+ }
+ else
+ {
+ return select(0, sa, NULL, NULL, NULL);
+ }
+}
+
+static bool
+socket_has_input(socket_set *sa, int fd, int idx)
+{
+ return (FD_ISSET(fd, sa) != 0);
+}
+
+#endif /* POLL_USING_WINDOWS_SELECT */
+
/* partial pthread implementation for Windows */
В списке pgsql-bugs по дате отправления: