Re: [PATCHES] autovacuum: multiple workers

2007-03-28 Thread Alvaro Herrera
Simon Riggs wrote:
 On Tue, 2007-03-27 at 17:41 -0400, Alvaro Herrera wrote:
 
  The main change is to have an array of Worker structs in shared memory;
  each worker checks the current table of all other Workers, and skips a
  table that's being vacuumed by any of them.  It also rechecks the table
  before vacuuming, which removes the problem of redundant vacuuming.
 
 Slightly OT: Personally, I'd like it if we added an array for all
 special backends, with configurable behaviour. That way it would be
 easier to have multiple copies of other backends of any flavour using
 the same code, as well as adding others without cutting and pasting each
 time. That part of the postmaster code has oozed sideways in the past
 few years and seems in need of some love. (A former sinner repents).

I'm not really thrilled about it, each case being so different from the
others.  For the autovac workers, for example, the array in shared
memory is kept on the autovac launcher, _not_ in the postmaster.  In the
postmaster, they are kept in the regular BackendList array, so they
don't fit on that array you describe.  And as far as the other processes
are concerned, every one of them is a special case, and we don't add new
ones frequently.  In fact, the autovac work is the only thing that has
added new processes in a long time, since the Windows port was
introduced (which required the logger process) and the bgwriter.

How would you make it configurable?  Have a struct containing function
pointers, each function being called when some event takes place?

What other auxiliary processes are you envisioning, anyway?

In any case I don't think this is something that would be good to attack
this late in the devel cycle -- we could discuss it for 8.4 though.

-- 
Alvaro Herrerahttp://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: [PATCHES] autovacuum: multiple workers

2007-03-28 Thread Simon Riggs
On Wed, 2007-03-28 at 09:39 -0400, Alvaro Herrera wrote:
 What other auxiliary processes are you envisioning, anyway?

WAL Writer, multiple bgwriters, checkpoint process, parallel query and
sort slavesplus all the ones I haven't dreamed of yet.

No need to agree with my short list, but we do seem to keep adding them
on a regular basis

 In any case I don't think this is something that would be good to
 attack
 this late in the devel cycle -- we could discuss it for 8.4 though.

OK

-- 
  Simon Riggs 
  EnterpriseDB   http://www.enterprisedb.com



---(end of broadcast)---
TIP 6: explain analyze is your friend


[PATCHES] autovacuum: multiple workers

2007-03-27 Thread Alvaro Herrera
Hi,

This is the patch to put multiple workers into autovacuum.  This patch
applies after the recheck patch I just posted.

The main change is to have an array of Worker structs in shared memory;
each worker checks the current table of all other Workers, and skips a
table that's being vacuumed by any of them.  It also rechecks the table
before vacuuming, which removes the problem of redundant vacuuming.

It also introduces the business of SIGUSR1 between workers and launcher.
The launcher keeps a database list in memory and schedules workers to
vacuum databases depending on that list.  The actual database selected
may differ from what was in the schedule; in that case, the list is
reconstructed.

There are two main FIXMEs in this code:

1. have the list reconstruction and scheduling be smarter so that
databases are not ganged together in the schedule.  The only difficulty
is keeping the sort order that the databases had.

2. have a way to clean up after failed workers filling up the Worker
array and thus starving other databases from vacuuming.  I don't really
know a way to do this that works in all cases.  The only idea I have so
far is that workers that started more than autovacuum_naptime seconds
ago are considered failed to start.


Neither of these is really minor, but I think they are solvable.

-- 
Alvaro Herrerahttp://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support
*** 14recheck/src/backend/postmaster/autovacuum.c	2007-03-27 16:43:31.0 -0400
--- 12vacuum/src/backend/postmaster/autovacuum.c	2007-03-27 17:40:19.0 -0400
***
*** 52,57 
--- 52,58 
  #include utils/syscache.h
  
  
+ static volatile sig_atomic_t got_SIGUSR1 = false;
  static volatile sig_atomic_t got_SIGHUP = false;
  static volatile sig_atomic_t avlauncher_shutdown_request = false;
  
***
*** 59,64 
--- 60,66 
   * GUC parameters
   */
  bool		autovacuum_start_daemon = false;
+ int			autovacuum_max_workers;
  int			autovacuum_naptime;
  int			autovacuum_vac_thresh;
  double		autovacuum_vac_scale;
***
*** 69,75 
  int			autovacuum_vac_cost_delay;
  int			autovacuum_vac_cost_limit;
  
! /* Flag to tell if we are in the autovacuum daemon process */
  static bool am_autovacuum_launcher = false;
  static bool am_autovacuum_worker = false;
  
--- 71,77 
  int			autovacuum_vac_cost_delay;
  int			autovacuum_vac_cost_limit;
  
! /* Flags to tell if we are in an autovacuum process */
  static bool am_autovacuum_launcher = false;
  static bool am_autovacuum_worker = false;
  
***
*** 86,91 
--- 88,94 
  typedef struct autovac_dbase
  {
  	Oid			ad_datid;
+ 	TimestampTz	ad_next_worker;
  	char	   *ad_name;
  	TransactionId ad_frozenxid;
  	PgStat_StatDBEntry *ad_entry;
***
*** 110,123 
  	int			at_vacuum_cost_limit;
  } autovac_table;
  
  typedef struct
  {
! 	Oid		process_db;			/* OID of database to process */
! 	int		worker_pid;			/* PID of the worker process, if any */
  } AutoVacuumShmemStruct;
  
  static AutoVacuumShmemStruct *AutoVacuumShmem;
  
  #ifdef EXEC_BACKEND
  static pid_t avlauncher_forkexec(void);
  static pid_t avworker_forkexec(void);
--- 113,158 
  	int			at_vacuum_cost_limit;
  } autovac_table;
  
+ /*-
+  * This struct holds information about a single worker's whereabouts.  We keep
+  * an array of these in shared memory, sized according to
+  * autovacuum_max_workers.
+  *
+  * wi_dboid		OID of the database this worker is supposed to work on
+  * wi_tableoid	OID of the table currently being vacuumed
+  * wi_workerpid	PID of the running worker, 0 if not yet started
+  * wi_finished	True when the worker is done and about to exit
+  *-
+  */
+ typedef struct
+ {
+ 	Oid			wi_dboid;
+ 	Oid			wi_tableoid;
+ 	int			wi_workerpid;
+ 	bool		wi_finished;
+ } WorkerInfo;
+ 
  typedef struct
  {
! 	pid_t		av_launcherpid;
! 	WorkerInfo	av_workers[1];
! 	/* VARIABLE LENGTH STRUCT */
  } AutoVacuumShmemStruct;
  
+ /* Macro to iterate over all workers.  Beware multiple evaluation of args! */
+ #define foreach_worker(_i, _worker) \
+ 	_worker = (WorkerInfo *) (AutoVacuumShmem + \
+ 			  offsetof(AutoVacuumShmemStruct, av_workers)); \
+ 	for (_i = 0; _i  autovacuum_max_workers; _i++, _worker += sizeof(WorkerInfo))
+ 
  static AutoVacuumShmemStruct *AutoVacuumShmem;
  
+ /* number of currently free worker slots; only valid in the launcher */
+ static int free_workers;
+ /* the database list in the launcher, and the context that contains it */
+ static Dllist *DatabaseList = NULL;
+ static MemoryContext DatabaseListCxt = NULL;
+ 
  #ifdef EXEC_BACKEND
  static pid_t avlauncher_forkexec(void);
  static pid_t avworker_forkexec(void);
***
*** 125,133 
  NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]);
  NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]);
  
! static void 

Re: [PATCHES] autovacuum: multiple workers

2007-03-27 Thread Simon Riggs
On Tue, 2007-03-27 at 17:41 -0400, Alvaro Herrera wrote:

 The main change is to have an array of Worker structs in shared memory;
 each worker checks the current table of all other Workers, and skips a
 table that's being vacuumed by any of them.  It also rechecks the table
 before vacuuming, which removes the problem of redundant vacuuming.

Slightly OT: Personally, I'd like it if we added an array for all
special backends, with configurable behaviour. That way it would be
easier to have multiple copies of other backends of any flavour using
the same code, as well as adding others without cutting and pasting each
time. That part of the postmaster code has oozed sideways in the past
few years and seems in need of some love. (A former sinner repents).

-- 
  Simon Riggs 
  EnterpriseDB   http://www.enterprisedb.com



---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster