cache_table_poc.patch
application/octet-stream
Filename: cache_table_poc.patch
Type: application/octet-stream
Part: 0
Message:
Re: Priority table or Cache table
Patch
Format: context
| File | + | − |
|---|---|---|
| src/backend/access/common/reloptions.c | 11 | 0 |
| src/backend/storage/buffer/buf_init.c | 14 | 0 |
| src/backend/storage/buffer/bufmgr.c | 18 | 0 |
| src/backend/storage/buffer/freelist.c | 29 | 0 |
| src/backend/utils/init/globals.c | 1 | 0 |
| src/backend/utils/misc/guc.c | 10 | 0 |
| src/backend/utils/misc/postgresql.conf.sample | 3 | 0 |
| src/bin/pgbench/pgbench.c | 8 | 0 |
| src/include/storage/buf_internals.h | 4 | 0 |
| src/include/storage/bufmgr.h | 9 | 0 |
| src/include/storage/smgr.h | 2 | 0 |
| src/include/utils/rel.h | 10 | 0 |
*** a/src/backend/access/common/reloptions.c
--- b/src/backend/access/common/reloptions.c
***************
*** 85,90 **** static relopt_bool boolRelOpts[] =
--- 85,98 ----
},
false
},
+ {
+ {
+ "buffer_cache",
+ "Enables buffer_cache option Table/Index.",
+ RELOPT_KIND_HEAP | RELOPT_KIND_BTREE
+ },
+ false
+ },
/* list terminator */
{{NULL}}
};
***************
*** 1230,1236 **** default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, analyze_scale_factor)},
{"user_catalog_table", RELOPT_TYPE_BOOL,
! offsetof(StdRdOptions, user_catalog_table)}
};
options = parseRelOptions(reloptions, validate, kind, &numoptions);
--- 1238,1246 ----
{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, analyze_scale_factor)},
{"user_catalog_table", RELOPT_TYPE_BOOL,
! offsetof(StdRdOptions, user_catalog_table)},
! {"buffer_cache", RELOPT_TYPE_BOOL,
! offsetof(StdRdOptions, buffer_cache) }
};
options = parseRelOptions(reloptions, validate, kind, &numoptions);
*** a/src/backend/storage/buffer/buf_init.c
--- b/src/backend/storage/buffer/buf_init.c
***************
*** 18,23 ****
--- 18,24 ----
#include "storage/buf_internals.h"
+ BufferPoolHeader *BufferPool;
BufferDescPadded *BufferDescriptors;
char *BufferBlocks;
***************
*** 65,71 **** void
InitBufferPool(void)
{
bool foundBufs,
! foundDescs;
/* Align descriptors to a cacheline boundary. */
BufferDescriptors = (BufferDescPadded *) CACHELINEALIGN(
--- 66,78 ----
InitBufferPool(void)
{
bool foundBufs,
! foundDescs,
! foundPoolHeader;
!
! /* Initialize the Buffer Pool Header data */
! BufferPool = (BufferPoolHeader *)
! ShmemInitStruct("Buffer pool",
! sizeof(BufferPoolHeader), &foundPoolHeader);
/* Align descriptors to a cacheline boundary. */
BufferDescriptors = (BufferDescPadded *) CACHELINEALIGN(
***************
*** 116,121 **** InitBufferPool(void)
--- 123,131 ----
/* Correct last entry of linked list */
GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
+
+ pg_atomic_init_u32(&BufferPool->current_buffer_cache_pages, 0);
+ pg_atomic_init_u32(&BufferPool->max_buffer_cache_pages,((NBuffers * buffer_cache_ratio) / 100));
}
/* Init other shared buffer-management stuff */
***************
*** 133,138 **** BufferShmemSize(void)
--- 143,151 ----
{
Size size = 0;
+ /* size of buffer Pool Header */
+ size = add_size(size, sizeof(BufferPoolHeader));
+
/* size of buffer descriptors */
size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
/* to allow aligning buffer descriptors */
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
***************
*** 1171,1182 **** BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
* 1 so that the buffer can survive one clock-sweep pass.)
*/
buf->tag = newTag;
! buf->flags &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR | BM_PERMANENT);
if (relpersistence == RELPERSISTENCE_PERMANENT)
buf->flags |= BM_TAG_VALID | BM_PERMANENT;
else
buf->flags |= BM_TAG_VALID;
buf->usage_count = 1;
UnlockBufHdr(buf);
--- 1171,1196 ----
* 1 so that the buffer can survive one clock-sweep pass.)
*/
buf->tag = newTag;
! buf->flags &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR | BM_PERMANENT | BM_BUFFER_CACHE_PAGE);
if (relpersistence == RELPERSISTENCE_PERMANENT)
buf->flags |= BM_TAG_VALID | BM_PERMANENT;
else
buf->flags |= BM_TAG_VALID;
buf->usage_count = 1;
+
+ if ((oldFlags & BM_BUFFER_CACHE_PAGE) && (smgr->is_a_buffer_cache_rel))
+ {
+ buf->flags |= BM_BUFFER_CACHE_PAGE;
+ }
+ else if (smgr->is_a_buffer_cache_rel)
+ {
+ buf->flags |= BM_BUFFER_CACHE_PAGE;
+ increment_buffer_cache_pages_counter();
+ }
+ else if (oldFlags & BM_BUFFER_CACHE_PAGE)
+ {
+ decrement_buffer_cache_pages_counter();
+ }
UnlockBufHdr(buf);
***************
*** 1288,1293 **** retry:
--- 1302,1310 ----
buf->flags = 0;
buf->usage_count = 0;
+ if (oldFlags & BM_BUFFER_CACHE_PAGE)
+ decrement_buffer_cache_pages_counter();
+
UnlockBufHdr(buf);
/*
*** a/src/backend/storage/buffer/freelist.c
--- b/src/backend/storage/buffer/freelist.c
***************
*** 101,106 **** typedef struct BufferAccessStrategyData
--- 101,129 ----
static volatile BufferDesc *GetBufferFromRing(BufferAccessStrategy strategy);
static void AddBufferToRing(BufferAccessStrategy strategy,
volatile BufferDesc *buf);
+ static bool is_buffer_cache_ratio_reached(void);
+
+ void
+ decrement_buffer_cache_pages_counter()
+ {
+ pg_atomic_fetch_sub_u32(&BufferPool->current_buffer_cache_pages, 1);
+ }
+
+ void
+ increment_buffer_cache_pages_counter()
+ {
+ pg_atomic_fetch_add_u32(&BufferPool->current_buffer_cache_pages, 1);
+ }
+
+ static bool
+ is_buffer_cache_ratio_reached()
+ {
+ uint32 current_pages = pg_atomic_read_u32(&BufferPool->current_buffer_cache_pages);
+ uint32 max_pages = pg_atomic_read_u32(&BufferPool->max_buffer_cache_pages);
+
+ return (current_pages < max_pages) ? false : true;
+ }
+
/*
* ClockSweepTick - Helper routine for StrategyGetBuffer()
***************
*** 305,313 **** StrategyGetBuffer(BufferAccessStrategy strategy)
LockBufHdr(buf);
if (buf->refcount == 0)
{
! if (buf->usage_count > 0)
{
buf->usage_count--;
trycounter = NBuffers;
}
else
--- 328,341 ----
LockBufHdr(buf);
if (buf->refcount == 0)
{
! if ((buf->flags & BM_BUFFER_CACHE_PAGE) && !is_buffer_cache_ratio_reached())
! {
! trycounter = NBuffers;
! }
! else if (buf->usage_count > 0)
{
buf->usage_count--;
+
trycounter = NBuffers;
}
else
*** a/src/backend/utils/init/globals.c
--- b/src/backend/utils/init/globals.c
***************
*** 116,121 **** int maintenance_work_mem = 16384;
--- 116,122 ----
* register background workers.
*/
int NBuffers = 1000;
+ int buffer_cache_ratio = 0;
int MaxConnections = 90;
int max_worker_processes = 8;
int MaxBackends = 0;
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 1811,1816 **** static struct config_int ConfigureNamesInt[] =
--- 1811,1826 ----
},
{
+ { "buffer_cache_ratio", PGC_POSTMASTER, RESOURCES_MEM,
+ gettext_noop("Sets the number of buffer cache ratio can be used for buffer cache relations from shared memory."),
+ NULL
+ },
+ &buffer_cache_ratio,
+ 0, 0, 75,
+ NULL, NULL, NULL
+ },
+
+ {
{"temp_buffers", PGC_USERSET, RESOURCES_MEM,
gettext_noop("Sets the maximum number of temporary buffers used by each session."),
NULL,
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 114,119 ****
--- 114,122 ----
#shared_buffers = 32MB # min 128kB
# (change requires restart)
+ #buffer_cache_ratio = 0; #specifies the ratio of shared buffers
+ #used for buffer cache relations
+ #(change requires restart)
#huge_pages = try # on, off, or try
# (change requires restart)
#temp_buffers = 8MB # min 800kB
*** a/src/bin/pgbench/pgbench.c
--- b/src/bin/pgbench/pgbench.c
***************
*** 1930,1938 **** init(bool is_no_vacuum)
}
};
static const char *const DDLINDEXes[] = {
! "alter table pgbench_branches add primary key (bid)",
! "alter table pgbench_tellers add primary key (tid)",
! "alter table pgbench_accounts add primary key (aid)"
};
static const char *const DDLKEYs[] = {
"alter table pgbench_tellers add foreign key (bid) references pgbench_branches",
--- 1930,1938 ----
}
};
static const char *const DDLINDEXes[] = {
! "alter table pgbench_branches add primary key (bid) with (buffer_cache=true)",
! "alter table pgbench_tellers add primary key (tid) with (buffer_cache=true)",
! "alter table pgbench_accounts add primary key (aid) with (buffer_cache=true)"
};
static const char *const DDLKEYs[] = {
"alter table pgbench_tellers add foreign key (bid) references pgbench_branches",
***************
*** 1973,1979 **** init(bool is_no_vacuum)
opts[0] = '\0';
if (ddl->declare_fillfactor)
snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
! " with (fillfactor=%d)", fillfactor);
if (tablespace != NULL)
{
char *escape_tablespace;
--- 1973,1983 ----
opts[0] = '\0';
if (ddl->declare_fillfactor)
snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
! " with (fillfactor=%d", fillfactor);
!
! snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
! "%s buffer_cache=true)", ddl->declare_fillfactor ? ",":" with (");
!
if (tablespace != NULL)
{
char *escape_tablespace;
*** a/src/include/storage/buf_internals.h
--- b/src/include/storage/buf_internals.h
***************
*** 40,45 ****
--- 40,46 ----
#define BM_CHECKPOINT_NEEDED (1 << 7) /* must write for checkpoint */
#define BM_PERMANENT (1 << 8) /* permanent relation (not
* unlogged) */
+ #define BM_BUFFER_CACHE_PAGE (1 << 9) /* Buffer used by a buffer cache rel */
typedef bits16 BufFlags;
***************
*** 227,232 **** extern void StrategyNotifyBgWriter(int bgwprocno);
--- 228,236 ----
extern Size StrategyShmemSize(void);
extern void StrategyInitialize(bool init);
+ extern void decrement_buffer_cache_pages_counter(void);
+ extern void increment_buffer_cache_pages_counter(void);
+
/* buf_table.c */
extern Size BufTableShmemSize(int size);
extern void InitBufTable(int size);
*** a/src/include/storage/bufmgr.h
--- b/src/include/storage/bufmgr.h
***************
*** 14,19 ****
--- 14,20 ----
#ifndef BUFMGR_H
#define BUFMGR_H
+ #include "port/atomics.h"
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufpage.h"
***************
*** 45,52 **** typedef enum
--- 46,61 ----
* replay; otherwise same as RBM_NORMAL */
} ReadBufferMode;
+ typedef struct BufferPoolHeader
+ {
+ pg_atomic_uint32 max_buffer_cache_pages;
+ pg_atomic_uint32 current_buffer_cache_pages;
+ } BufferPoolHeader;
+
/* in globals.c ... this duplicates miscadmin.h */
extern PGDLLIMPORT int NBuffers;
+ extern int buffer_cache_ratio;
+ extern BufferPoolHeader *BufferPool;
/* in bufmgr.c */
extern bool zero_damaged_pages;
*** a/src/include/storage/smgr.h
--- b/src/include/storage/smgr.h
***************
*** 56,61 **** typedef struct SMgrRelationData
--- 56,63 ----
BlockNumber smgr_fsm_nblocks; /* last known size of fsm fork */
BlockNumber smgr_vm_nblocks; /* last known size of vm fork */
+ bool is_a_buffer_cache_rel; /* Flag to indicate the relation buffer_cache */
+
/* additional public fields may someday exist here */
/*
*** a/src/include/utils/rel.h
--- b/src/include/utils/rel.h
***************
*** 220,225 **** typedef struct StdRdOptions
--- 220,227 ----
AutoVacOpts autovacuum; /* autovacuum-related options */
bool user_catalog_table; /* use as an additional catalog
* relation */
+ bool buffer_cache; /* Use buffer cache for relation
+ * if available */
} StdRdOptions;
#define HEAP_MIN_FILLFACTOR 10
***************
*** 256,261 **** typedef struct StdRdOptions
--- 258,270 ----
((relation)->rd_options ? \
((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false)
+ /*
+ * RelationUsesBufferCache
+ * Returns the relation's buffer_cache option.
+ */
+ #define RelationUsesBufferCache(relation) \
+ ((relation)->rd_options ? \
+ ((StdRdOptions *) (relation)->rd_options)->buffer_cache : false)
/*
* ViewOptions
***************
*** 390,395 **** typedef struct ViewOptions
--- 399,405 ----
do { \
if ((relation)->rd_smgr == NULL) \
smgrsetowner(&((relation)->rd_smgr), smgropen((relation)->rd_node, (relation)->rd_backend)); \
+ (relation)->rd_smgr->is_a_buffer_cache_rel = RelationUsesBufferCache(relation); \
} while (0)
/*