(unnamed)

text/plain

Filename: (unnamed)
Type: text/plain
Part: 0
Message: Stats collector performance improvement
Index: src/backend/postmaster/pgstat.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v
retrieving revision 1.116
diff -c -c -r1.116 pgstat.c
*** src/backend/postmaster/pgstat.c	2 Jan 2006 00:58:00 -0000	1.116
--- src/backend/postmaster/pgstat.c	2 Jan 2006 18:36:43 -0000
***************
*** 1911,1916 ****
--- 1911,1918 ----
  	 */
  	for (;;)
  	{
+ loop_again:
+ 
  		FD_ZERO(&rfds);
  		FD_ZERO(&wfds);
  		maxfd = -1;
***************
*** 1970,2014 ****
  		 */
  		if (FD_ISSET(pgStatSock, &rfds))
  		{
! 			len = recv(pgStatSock, (char *) &input_buffer,
! 					   sizeof(PgStat_Msg), 0);
! 			if (len < 0)
! 				ereport(ERROR,
! 						(errcode_for_socket_access(),
! 						 errmsg("could not read statistics message: %m")));
! 
! 			/*
! 			 * We ignore messages that are smaller than our common header
! 			 */
! 			if (len < sizeof(PgStat_MsgHdr))
! 				continue;
! 
! 			/*
! 			 * The received length must match the length in the header
! 			 */
! 			if (input_buffer.msg_hdr.m_size != len)
! 				continue;
! 
  			/*
! 			 * O.K. - we accept this message.  Copy it to the circular
! 			 * msgbuffer.
  			 */
! 			frm = 0;
! 			while (len > 0)
  			{
! 				xfr = PGSTAT_RECVBUFFERSZ - msg_recv;
! 				if (xfr > len)
! 					xfr = len;
! 				Assert(xfr > 0);
! 				memcpy(msgbuffer + msg_recv,
! 					   ((char *) &input_buffer) + frm,
! 					   xfr);
! 				msg_recv += xfr;
! 				if (msg_recv == PGSTAT_RECVBUFFERSZ)
! 					msg_recv = 0;
! 				msg_have += xfr;
! 				frm += xfr;
! 				len -= xfr;
  			}
  		}
  
--- 1972,2033 ----
  		 */
  		if (FD_ISSET(pgStatSock, &rfds))
  		{
! 			int loops = 0;
! 			
  			/*
! 			 *	While pipewrite() can send multiple data packets, recv() pulls
! 			 *	only a single packet per call.  For busy systems, doing
! 			 *	multiple recv() calls and then one pipewrite() can improve
! 			 *	query speed by 40%.  25 was chosen because 25 packets should
! 			 *	easily fit in a single pipewrite() call.  recv()'s socket is
! 			 *	non-blocking.
  			 */
! 			while (++loops < 25 &&
! 				   (len = recv(pgStatSock, (char *) &input_buffer,
! 							   sizeof(PgStat_Msg), 0)) != 0)
  			{
! 				if (len < 0)
! 				{
! 					if (errno == EAGAIN)
! 						continue;
! 					ereport(ERROR,
! 							(errcode_for_socket_access(),
! 							 errmsg("could not read statistics message: %m")));
! 				}
! 	
! 				/*
! 				 * We ignore messages that are smaller than our common header
! 				 */
! 				if (len < sizeof(PgStat_MsgHdr))
! 					goto loop_again;
! 	
! 				/*
! 				 * The received length must match the length in the header
! 				 */
! 				if (input_buffer.msg_hdr.m_size != len)
! 					goto loop_again;
! 	
! 				/*
! 				 * O.K. - we accept this message.  Copy it to the circular
! 				 * msgbuffer.
! 				 */
! 				frm = 0;
! 				while (len > 0)
! 				{
! 					xfr = PGSTAT_RECVBUFFERSZ - msg_recv;
! 					if (xfr > len)
! 						xfr = len;
! 					Assert(xfr > 0);
! 					memcpy(msgbuffer + msg_recv,
! 						   ((char *) &input_buffer) + frm,
! 						   xfr);
! 					msg_recv += xfr;
! 					if (msg_recv == PGSTAT_RECVBUFFERSZ)
! 						msg_recv = 0;
! 					msg_have += xfr;
! 					frm += xfr;
! 					len -= xfr;
! 				}
  			}
  		}
  
***************
*** 2023,2029 ****
  		 * caught up, or because more data arrives so that we have more than
  		 * PIPE_BUF bytes buffered).  This is not good, but is there any way
  		 * around it?  We have no way to tell when the collector has caught
! 		 * up...
  		 */
  		if (FD_ISSET(writePipe, &wfds))
  		{
--- 2042,2048 ----
  		 * caught up, or because more data arrives so that we have more than
  		 * PIPE_BUF bytes buffered).  This is not good, but is there any way
  		 * around it?  We have no way to tell when the collector has caught
! 		 * up.  Followup, the pipe rarely fills up.
  		 */
  		if (FD_ISSET(writePipe, &wfds))
  		{