Alvaro Herrera wrote:

> Darcy Buskermolen noticed that when one has many databases, the autovac
> launcher starts eating too much CPU.
> 
> I tried it here with 200 databases and indeed it does seem to eat its
> share.  Even with the default naptime, which I wouldn't have thought
> that was too high (it does make the launcher wake up about three times a
> second though).

This patch does not solve the whole problem but it alleviates it a bit
by throttling pgstat reads.  One problem with it is that the interval
for this increases:

        /*
         * Check whether pgstat data still says we need to vacuum this table.
         * It could have changed if something else processed the table while we
         * weren't looking.
         *
         * FIXME we ignore the possibility that the table was finished being
         * vacuumed in the last 500ms (PGSTAT_STAT_INTERVAL).  This is a bug.
         */
        MemoryContextSwitchTo(AutovacMemCxt);
        tab = table_recheck_autovac(relid);

which could be a problem in itself, by causing unnecessary vacuums.

Opinions?

-- 
Alvaro Herrera                 http://www.amazon.com/gp/registry/DXLWNGRJD34J
"In Europe they call me Niklaus Wirth; in the US they call me Nickel's worth.
 That's because in Europe they call me by name, and in the US by value!"
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.58
diff -c -p -r1.58 autovacuum.c
*** src/backend/postmaster/autovacuum.c	12 Sep 2007 22:14:59 -0000	1.58
--- src/backend/postmaster/autovacuum.c	13 Sep 2007 16:57:59 -0000
*************** static void avl_sighup_handler(SIGNAL_AR
*** 291,296 ****
--- 291,297 ----
  static void avl_sigusr1_handler(SIGNAL_ARGS);
  static void avl_sigterm_handler(SIGNAL_ARGS);
  static void avl_quickdie(SIGNAL_ARGS);
+ static void autovac_refresh_stats(void);
  
  
  
*************** AutoVacLauncherMain(int argc, char *argv
*** 488,494 ****
  		DatabaseListCxt = NULL;
  		DatabaseList = NULL;
  
! 		/* Make sure pgstat also considers our stat data as gone */
  		pgstat_clear_snapshot();
  
  		/* Now we can allow interrupts again */
--- 489,498 ----
  		DatabaseListCxt = NULL;
  		DatabaseList = NULL;
  
! 		/*
! 		 * Make sure pgstat also considers our stat data as gone.  Note: we
! 		 * musn't use autovac_refresh_stats here.
! 		 */
  		pgstat_clear_snapshot();
  
  		/* Now we can allow interrupts again */
*************** rebuild_database_list(Oid newdb)
*** 836,842 ****
  	HTAB	   *dbhash;
  
  	/* use fresh stats */
! 	pgstat_clear_snapshot();
  
  	newcxt = AllocSetContextCreate(AutovacMemCxt,
  								   "AV dblist",
--- 840,846 ----
  	HTAB	   *dbhash;
  
  	/* use fresh stats */
! 	autovac_refresh_stats();
  
  	newcxt = AllocSetContextCreate(AutovacMemCxt,
  								   "AV dblist",
*************** do_start_worker(void)
*** 1063,1069 ****
  	oldcxt = MemoryContextSwitchTo(tmpcxt);
  
  	/* use fresh stats */
! 	pgstat_clear_snapshot();
  
  	/* Get a list of databases */
  	dblist = get_database_list();
--- 1067,1073 ----
  	oldcxt = MemoryContextSwitchTo(tmpcxt);
  
  	/* use fresh stats */
! 	autovac_refresh_stats();
  
  	/* Get a list of databases */
  	dblist = get_database_list();
*************** table_recheck_autovac(Oid relid)
*** 2258,2264 ****
  	PgStat_StatDBEntry *dbentry;
  
  	/* use fresh stats */
! 	pgstat_clear_snapshot();
  
  	shared = pgstat_fetch_stat_dbentry(InvalidOid);
  	dbentry = pgstat_fetch_stat_dbentry(MyDatabaseId);
--- 2262,2268 ----
  	PgStat_StatDBEntry *dbentry;
  
  	/* use fresh stats */
! 	autovac_refresh_stats();
  
  	shared = pgstat_fetch_stat_dbentry(InvalidOid);
  	dbentry = pgstat_fetch_stat_dbentry(MyDatabaseId);
*************** AutoVacuumShmemInit(void)
*** 2734,2736 ****
--- 2738,2759 ----
  	else
  		Assert(found);
  }
+ 
+ /*
+  * Refresh pgstats data in an autovacuum process, at most every 500 ms.  This
+  * is to avoid rereading the pgstats files too many times in quick succession.
+  */
+ static void
+ autovac_refresh_stats(void)
+ {
+ 	static TimestampTz last_read = 0;
+ 	TimestampTz current_time;
+ 
+ 	current_time = GetCurrentTimestamp();
+ 
+ 	if (!TimestampDifferenceExceeds(last_read, current_time, 500))
+ 		return;
+ 
+ 	pgstat_clear_snapshot();
+ 	last_read = current_time;
+ }
---------------------------(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

Reply via email to