diff --git a/configure b/configure
index 2821a8f7e4..c1ba3c1477 100755
--- a/configure
+++ b/configure
@@ -9053,6 +9053,62 @@ if test "$ac_res" != no; then :
 
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ppoll" >&5
+$as_echo_n "checking for library containing ppoll... " >&6; }
+if ${ac_cv_search_ppoll+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ppoll ();
+int
+main ()
+{
+return ppoll ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' c; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_ppoll=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_ppoll+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_ppoll+:} false; then :
+
+else
+  ac_cv_search_ppoll=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ppoll" >&5
+$as_echo "$ac_cv_search_ppoll" >&6; }
+ac_res=$ac_cv_search_ppoll
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
 # Solaris:
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
 $as_echo_n "checking for library containing fdatasync... " >&6; }
@@ -12517,7 +12573,7 @@ fi
 LIBS_including_readline="$LIBS"
 LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
 
-for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
+for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll ppoll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.in b/configure.in
index a1696db921..b0b24867a6 100644
--- a/configure.in
+++ b/configure.in
@@ -1058,6 +1058,7 @@ AC_SEARCH_LIBS(getopt_long, [getopt gnugetopt])
 AC_SEARCH_LIBS(crypt, crypt)
 AC_SEARCH_LIBS(shm_open, rt)
 AC_SEARCH_LIBS(shm_unlink, rt)
+AC_SEARCH_LIBS(ppoll, c)
 # Solaris:
 AC_SEARCH_LIBS(fdatasync, [rt posix4])
 # Required for thread_test.c on Solaris
@@ -1457,7 +1458,7 @@ PGAC_FUNC_WCSTOMBS_L
 LIBS_including_readline="$LIBS"
 LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
 
-AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
+AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll ppoll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
 
 AC_REPLACE_FUNCS(fseeko)
 case $host_os in
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 163dcad137..9a6b95d05b 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -46,6 +46,9 @@
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
 
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>		/* for getrlimit */
@@ -55,6 +58,10 @@
 #define M_PI 3.14159265358979323846
 #endif
 
+#ifdef HAVE_PPOLL
+#define USE_PPOLL 1
+#endif
+
 #include "pgbench.h"
 
 #define ERRCODE_UNDEFINED_TABLE  "42P01"
@@ -89,6 +96,27 @@ static int	pthread_join(pthread_t th, void **thread_return);
 #define MAXCLIENTS	1024
 #endif
 
+#ifdef USE_PPOLL
+#define SCKTWTMTHD "ppoll"
+#undef MAXCLIENTS
+#define POLL_EVENTS (POLLIN|POLLPRI|POLLRDHUP)
+#define POLL_FAIL (POLLERR|POLLHUP|POLLNVAL|POLLRDHUP)
+#define PFD_CLREV(s) { do { if ((s)->pfdp) { ((s)->pfdp)->revents = 0; } } while(0); }
+#define PFD_ZERO(s) { do { if ((s)->pfdp) { memset((s)->pfdp, 0, sizeof(struct pollfd)); } } while(0); }
+#define PFD_SETFD(s) { do { ((s)->pfdp)->fd = PQsocket((s)->con); } while(0); }
+#define	PFD_STRUCT_POLLFD(p)	struct pollfd   (p);
+#define PFD_THREAD_FREE(t) { do { if ((t)->pfds) { pg_free((t)->pfds); (t)->pfds = NULL; } } while (0); }
+#define PFD_THREAD_INIT(t,s,n) { do { int _i; (t)->pfds = (struct pollfd *) pg_malloc0(sizeof(struct pollfd) * (n)); for (_i = 0; _i < (n); _i++) { (s)[_i].pfdp = &(t)->pfds[_i]; } } while (0); } 
+#else
+#define SCKTWTMTHD "select"
+#define PFD_CLREV(s)
+#define PFD_ZERO(s)
+#define PFD_SETFD(s)
+#define PFD_STRUCT_POLLFD(p)
+#define PFD_THREAD_FREE(t)
+#define PFD_THREAD_INIT(t,s,n)
+#endif
+
 #define LOG_STEP_SECONDS	5	/* seconds between log messages */
 #define DEFAULT_NXACTS	10		/* default nxacts */
 
@@ -259,6 +287,7 @@ typedef struct
 	/* per client collected stats */
 	int64		cnt;			/* transaction count */
 	int			ecnt;			/* error count */
+	PFD_STRUCT_POLLFD(*pfdp)
 } CState;
 
 /*
@@ -273,6 +302,7 @@ typedef struct
 	unsigned short random_state[3];		/* separate randomness for each thread */
 	int64		throttle_trigger;		/* previous/next throttling (us) */
 	FILE	   *logfile;		/* where to log, or NULL */
+	PFD_STRUCT_POLLFD(*pfds)
 
 	/* per thread collected stats */
 	instr_time	start_time;		/* thread start time */
@@ -386,6 +416,7 @@ static void pgbench_error(const char *fmt,...) pg_attribute_printf(1, 2);
 static void addScript(ParsedScript script);
 static void *threadRun(void *arg);
 static void setalarm(int seconds);
+static void finishCon(CState *st);
 
 
 /* callback functions for our flex lexer */
@@ -1734,11 +1765,7 @@ preparedStatementName(char *buffer, int file, int state)
 static bool
 clientDone(CState *st)
 {
-	if (st->con != NULL)
-	{
-		PQfinish(st->con);
-		st->con = NULL;
-	}
+	finishCon(st);
 	return false;				/* always false */
 }
 
@@ -1914,10 +1941,7 @@ top:
 		if (commands[st->state + 1] == NULL)
 		{
 			if (is_connect)
-			{
-				PQfinish(st->con);
-				st->con = NULL;
-			}
+				finishCon(st);
 
 			++st->cnt;
 			if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
@@ -1968,6 +1992,7 @@ top:
 		st->sleeping = false;
 		st->throttling = false;
 		memset(st->prepared, 0, sizeof(st->prepared));
+		PFD_SETFD(st);
 	}
 
 	/*
@@ -2315,13 +2340,7 @@ disconnect_all(CState *state, int length)
 	int			i;
 
 	for (i = 0; i < length; i++)
-	{
-		if (state[i].con)
-		{
-			PQfinish(state[i].con);
-			state[i].con = NULL;
-		}
-	}
+		finishCon(&state[i]);
 }
 
 /* create tables and setup data */
@@ -3495,7 +3514,11 @@ main(int argc, char **argv)
 			case 'c':
 				benchmarking_option_set = true;
 				nclients = atoi(optarg);
+#ifdef USE_PPOLL
+				if (nclients <= 0 )
+#else
 				if (nclients <= 0 || nclients > MAXCLIENTS)
+#endif
 				{
 					fprintf(stderr, "invalid number of clients: \"%s\"\n",
 							optarg);
@@ -3756,6 +3779,14 @@ main(int argc, char **argv)
 		}
 	}
 
+	/*
+	 * Don't need more threads than there are clients.  (This is not merely an
+	 * optimization; throttle_delay is calculated incorrectly below if some
+	 * threads have no clients assigned to them.)
+	 */
+	if (nthreads > nclients)
+		nthreads = nclients;
+
 	/* set default script if none */
 	if (num_scripts == 0 && !is_init_mode)
 	{
@@ -3779,14 +3810,6 @@ main(int argc, char **argv)
 	if (num_scripts > 1)
 		per_script_stats = true;
 
-	/*
-	 * Don't need more threads than there are clients.  (This is not merely an
-	 * optimization; throttle_delay is calculated incorrectly below if some
-	 * threads have no clients assigned to them.)
-	 */
-	if (nthreads > nclients)
-		nthreads = nclients;
-
 	/* compute a per thread delay */
 	throttle_delay *= nthreads;
 
@@ -4162,6 +4185,8 @@ threadRun(void *arg)
 		}
 	}
 
+	PFD_THREAD_INIT(thread, state, nstate);
+
 	if (!is_connect)
 	{
 		/* make connections to the database */
@@ -4169,6 +4194,7 @@ threadRun(void *arg)
 		{
 			if ((state[i].con = doConnect()) == NULL)
 				goto done;
+			PFD_SETFD(&state[i]);
 		}
 	}
 
@@ -4192,28 +4218,32 @@ threadRun(void *arg)
 			fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
 					sql_script[st->use_file].desc);
 		if (!doCustom(thread, st, &aggs))
+		{
 			remains--;			/* I've aborted */
+			PFD_ZERO(st);
+		}
 
 		if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)
 		{
 			fprintf(stderr, "client %d aborted in state %d; execution of meta-command failed\n",
 					i, st->state);
 			remains--;			/* I've aborted */
-			PQfinish(st->con);
-			st->con = NULL;
+			finishCon(st);
 		}
 	}
 
 	while (remains > 0)
 	{
-		fd_set		input_mask;
 		int			maxsock;	/* max socket number to be waited */
 		int64		now_usec = 0;
 		int64		min_usec;
+#ifndef USE_PPOLL
+		fd_set		input_mask;
 
 		FD_ZERO(&input_mask);
-
 		maxsock = -1;
+#endif
+
 		min_usec = PG_INT64_MAX;
 		for (i = 0; i < nstate; i++)
 		{
@@ -4233,8 +4263,7 @@ threadRun(void *arg)
 					remains--;
 					st->sleeping = false;
 					st->throttling = false;
-					PQfinish(st->con);
-					st->con = NULL;
+					finishCon(st);
 					continue;
 				}
 				else	/* just a nap from the script */
@@ -4267,10 +4296,16 @@ threadRun(void *arg)
 				goto done;
 			}
 
+#ifdef USE_PPOLL
+			maxsock = 0;
+			(st->pfdp)->events = POLL_EVENTS;
+			(st->pfdp)->revents = 0;
+#else
 			FD_SET(sock, &input_mask);
 
 			if (maxsock < sock)
 				maxsock = sock;
+#endif
 		}
 
 		/* also wake up to print the next progress report on time */
@@ -4302,20 +4337,32 @@ threadRun(void *arg)
 
 			if (min_usec != PG_INT64_MAX)
 			{
+#ifdef USE_PPOLL
+				struct timespec timeout;
+
+				timeout.tv_sec = min_usec / 1000000;
+				timeout.tv_nsec = min_usec % 1000000000;
+				nsocks = ppoll(thread->pfds, nstate, &timeout, NULL);
+#else
 				struct timeval timeout;
 
 				timeout.tv_sec = min_usec / 1000000;
 				timeout.tv_usec = min_usec % 1000000;
 				nsocks = select(maxsock + 1, &input_mask, NULL, NULL, &timeout);
+#endif
 			}
 			else
+#ifdef USE_PPOLL
+				nsocks = ppoll(thread->pfds, nstate, NULL, NULL);
+#else
 				nsocks = select(maxsock + 1, &input_mask, NULL, NULL, NULL);
+#endif
 			if (nsocks < 0)
 			{
 				if (errno == EINTR)
 					continue;
 				/* must be something wrong */
-				fprintf(stderr, "select() failed: %s\n", strerror(errno));
+				fprintf(stderr, "%s() failed: %s\n", SCKTWTMTHD, strerror(errno));
 				goto done;
 			}
 		}
@@ -4337,18 +4384,36 @@ threadRun(void *arg)
 							PQerrorMessage(st->con));
 					goto done;
 				}
+#ifdef USE_PPOLL
+				if ((st->pfdp)->revents & POLL_FAIL)
+				{
+					fprintf(stderr,
+						"ppoll() fail - errno: %d, i: %d, events: %x\n",
+						errno, i, ((st->pfdp)->revents & POLL_FAIL));
+				}
+
+				if (((st->pfdp)->revents) ||
+#else
 				if (FD_ISSET(sock, &input_mask) ||
+#endif
 					commands[st->state]->type == META_COMMAND)
 				{
 					if (!doCustom(thread, st, &aggs))
+					{
 						remains--;		/* I've aborted */
+						PFD_ZERO(st);
+					}
 				}
+				PFD_CLREV(st);
 			}
 			else if (is_connect && st->sleeping)
 			{
 				/* it is sleeping for throttling, maybe it is done, let us try */
 				if (!doCustom(thread, st, &aggs))
+				{
 					remains--;
+					PFD_ZERO(st);
+				}
 			}
 
 			if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)
@@ -4356,8 +4421,7 @@ threadRun(void *arg)
 				fprintf(stderr, "client %d aborted in state %d; execution of meta-command failed\n",
 						i, st->state);
 				remains--;		/* I've aborted */
-				PQfinish(st->con);
-				st->con = NULL;
+				finishCon(st);
 			}
 		}
 
@@ -4460,9 +4524,21 @@ done:
 		}
 		fclose(thread->logfile);
 	}
+	PFD_THREAD_FREE(thread);
 	return NULL;
 }
 
+static void
+finishCon(CState *st)
+{
+	if (st->con)
+	{
+		PQfinish(st->con);
+		st->con = NULL;
+	}
+	PFD_ZERO(st);
+}
+
 /*
  * Support for duration option: set timer_exceeded after so many seconds.
  */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index a152371e61..83bfbfac47 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -393,6 +393,9 @@
 /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */
 #undef HAVE_PPC_LWARX_MUTEX_HINT
 
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
 /* Define to 1 if you have the `pstat' function. */
 #undef HAVE_PSTAT
 
