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