diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index b423c8fdbe..87a251915a 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.110 2004/02/03 17:34:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.111 2004/02/06 19:36:17 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -586,6 +586,26 @@ btbulkdelete(PG_FUNCTION_ARGS) CHECK_FOR_INTERRUPTS(); + /* + * If we're called by a cost based vacuum, do the + * napping in case the balance exceeded the limit. + */ + if (VacuumCostActive && !InterruptPending && + VacuumCostBalance >= VacuumCostLimit) + { + int msec; + + msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit; + if (msec < VacuumCostNaptime * 4) + PG_MSLEEP(msec); + else + PG_MSLEEP(VacuumCostNaptime * 4); + + VacuumCostBalance = 0; + + CHECK_FOR_INTERRUPTS(); + } + ndeletable = 0; page = BufferGetPage(buf); opaque = (BTPageOpaque) PageGetSpecialPointer(page); diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 14c66b498d..c271152877 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -31,7 +31,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.34 2004/02/03 17:34:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.35 2004/02/06 19:36:17 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -148,6 +148,11 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) vac_open_indexes(onerel, &nindexes, &Irel); hasindex = (nindexes > 0); + /* Turn on vacuum cost accounting */ + if (VacuumCostNaptime > 0) + VacuumCostActive = true; + VacuumCostBalance = 0; + /* Do the vacuuming */ lazy_scan_heap(onerel, vacrelstats, Irel, nindexes); @@ -168,6 +173,9 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) /* Update shared free space map with final free space info */ lazy_update_fsm(onerel, vacrelstats); + /* Turn off vacuum cost accounting */ + VacuumCostActive = false; + /* Update statistics in pg_class */ vac_update_relstats(RelationGetRelid(onerel), vacrelstats->rel_pages, vacrelstats->rel_tuples, hasindex); @@ -228,6 +236,25 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, CHECK_FOR_INTERRUPTS(); + /* + * Do the napping in a cost based vacuum. + */ + if (VacuumCostActive && !InterruptPending && + VacuumCostBalance >= VacuumCostLimit) + { + int msec; + + msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit; + if (msec < VacuumCostNaptime * 4) + PG_MSLEEP(msec); + else + PG_MSLEEP(VacuumCostNaptime * 4); + + VacuumCostBalance = 0; + + CHECK_FOR_INTERRUPTS(); + } + /* * If we are close to overrunning the available space for * dead-tuple TIDs, pause and do a cycle of vacuuming before we @@ -469,6 +496,25 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) CHECK_FOR_INTERRUPTS(); + /* + * Do the napping in a cost based vacuum. + */ + if (VacuumCostActive && !InterruptPending && + VacuumCostBalance >= VacuumCostLimit) + { + int msec; + + msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit; + if (msec < VacuumCostNaptime * 4) + PG_MSLEEP(msec); + else + PG_MSLEEP(VacuumCostNaptime * 4); + + VacuumCostBalance = 0; + + CHECK_FOR_INTERRUPTS(); + } + tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples[tupindex]); buf = ReadBuffer(onerel, tblk); LockBufferForCleanup(buf); @@ -800,6 +846,25 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats) CHECK_FOR_INTERRUPTS(); + /* + * Do the napping in a cost based vacuum. + */ + if (VacuumCostActive && !InterruptPending && + VacuumCostBalance >= VacuumCostLimit) + { + int msec; + + msec = VacuumCostNaptime * VacuumCostBalance / VacuumCostLimit; + if (msec < VacuumCostNaptime * 4) + PG_MSLEEP(msec); + else + PG_MSLEEP(VacuumCostNaptime * 4); + + VacuumCostBalance = 0; + + CHECK_FOR_INTERRUPTS(); + } + blkno--; buf = ReadBuffer(onerel, blkno); diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index cb82159aff..b927b5ea5e 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.155 2004/02/04 01:24:53 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.156 2004/02/06 19:36:18 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -576,6 +576,12 @@ write_buffer(Buffer buffer, bool release) LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); Assert(bufHdr->refcount > 0); + /* + * If the buffer is not dirty yet, do vacuum cost accounting. + */ + if (!(bufHdr->flags & BM_DIRTY) && VacuumCostActive) + VacuumCostBalance += VacuumCostPageDirty; + bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); if (release) diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6388bc724d..74ec4518ab 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/freelist.c,v 1.39 2004/01/15 16:14:26 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/freelist.c,v 1.40 2004/02/06 19:36:18 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -31,6 +31,7 @@ #include "storage/ipc.h" #include "storage/proc.h" #include "access/xact.h" +#include "miscadmin.h" #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -237,6 +238,12 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck) strategy_get_from = STRAT_LIST_T2; } + /* + * Do the cost accounting for vacuum + */ + if (VacuumCostActive) + VacuumCostBalance += VacuumCostPageMiss; + /* report cache miss */ return NULL; } @@ -250,6 +257,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck) * Count hits */ StrategyControl->num_hit[cdb->list]++; + if (VacuumCostActive) + VacuumCostBalance += VacuumCostPageHit; /* * If this is a T2 hit, we simply move the CDB to the diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 1ea95d2e50..735e5aa69d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.388 2004/02/03 17:34:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.389 2004/02/06 19:36:18 wieck Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -2707,6 +2707,11 @@ PostgresMain(int argc, char *argv[], const char *username) InError = false; xact_started = false; + /* + * Clear flag that causes accounting for cost based vacuum. + */ + VacuumCostActive = false; + /* * If we were handling an extended-query-protocol message, * initiate skip till next Sync. This also causes us not to issue diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index c170ae603d..f916d013d1 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.82 2004/02/03 17:34:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.83 2004/02/06 19:36:18 wieck Exp $ * * NOTES * Globals used all over the place should be declared here and not @@ -81,3 +81,11 @@ bool allowSystemTableMods = false; int work_mem = 1024; int maintenance_work_mem = 16384; int NBuffers = 1000; + +int VacuumCostPageHit = 1; +int VacuumCostPageMiss = 10; +int VacuumCostPageDirty = 20; +int VacuumCostLimit = 200; +int VacuumCostBalance = 0; +int VacuumCostNaptime = 0; +bool VacuumCostActive = false; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index eb79ea2c62..7fe7c33cf8 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.185 2004/02/04 01:24:53 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.186 2004/02/06 19:36:18 wieck Exp $ * *-------------------------------------------------------------------- */ @@ -1047,6 +1047,51 @@ static struct config_int ConfigureNamesInt[] = 16384, 1024, INT_MAX / 1024, NULL, NULL }, + { + {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES, + gettext_noop("Vacuum cost for a page found in the buffer cache."), + NULL + }, + &VacuumCostPageHit, + 1, 0, 10000, NULL, NULL + }, + + { + {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES, + gettext_noop("Vacuum cost for a page not found in the buffer cache."), + NULL + }, + &VacuumCostPageMiss, + 10, 0, 10000, NULL, NULL + }, + + { + {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES, + gettext_noop("Vacuum cost for a page dirtied by vacuum."), + NULL + }, + &VacuumCostPageDirty, + 20, 0, 10000, NULL, NULL + }, + + { + {"vacuum_cost_limit", PGC_USERSET, RESOURCES, + gettext_noop("Vacuum cost amount available before napping."), + NULL + }, + &VacuumCostLimit, + 200, 1, 10000, NULL, NULL + }, + + { + {"vacuum_cost_naptime", PGC_USERSET, RESOURCES, + gettext_noop("Vacuum cost naptime in milliseconds."), + NULL + }, + &VacuumCostNaptime, + 0, 0, 1000, NULL, NULL + }, + { {"max_files_per_process", PGC_BACKEND, RESOURCES_KERNEL, gettext_noop("Sets the maximum number of simultaneously open files for each server process."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index ad6f6bfcfe..ee7b47c04d 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -60,6 +60,12 @@ #maintenance_work_mem = 16384 # min 1024, size in KB #debug_shared_buffers = 0 # 0-600 seconds +#vacuum_cost_page_hit = 1 # 0-10000 credits +#vacuum_cost_page_miss = 10 # 0-10000 credits +#vacuum_cost_page_dirty = 20 # 0-10000 credits +#vacuum_cost_limit = 200 # 0-10000 credits +#vacuum_cost_naptime = 50 # 0-1000 milliseconds + # - Background writer - #bgwriter_delay = 200 # 10-5000 milliseconds #bgwriter_percent = 1 # 0-100% of dirty buffers diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index a7fe724533..1f71a434c1 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.150 2004/02/03 17:34:03 tgl Exp $ + * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.151 2004/02/06 19:36:18 wieck Exp $ * * NOTES * some of the information in this file should be moved to @@ -106,11 +106,19 @@ do { \ delay.tv_usec = ((_usec) % 1000000); \ (void) select(0, NULL, NULL, NULL, &delay); \ } while(0) +#define PG_MSLEEP(_msec) \ +do { \ + struct timeval _delay; \ + _delay.tv_sec = (_msec) / 1000; \ + _delay.tv_usec = ((_msec) % 1000) * 1000; \ + (void) select (0, NULL, NULL, NULL, &_delay); \ +} while(0) #else #define PG_USLEEP(_usec) \ do { \ SleepEx(((_usec) < 500 ? 1 : ((_usec) + 500) / 1000), TRUE); \ } while(0) +#define PG_MSLEEP(_msec) PG_USLEEP((_msec) * 1000) #endif #ifdef WIN32 @@ -209,6 +217,15 @@ extern bool enableFsync; extern bool allowSystemTableMods; extern DLLIMPORT int work_mem; extern DLLIMPORT int maintenance_work_mem; +extern int VacuumMem; + +extern int VacuumCostPageHit; +extern int VacuumCostPageMiss; +extern int VacuumCostPageDirty; +extern int VacuumCostLimit; +extern int VacuumCostBalance; +extern int VacuumCostNaptime; +extern bool VacuumCostActive; /* * A few postmaster startup options are exported here so the