v1-0001-Add-pg_buffercache_evict_all-function-for-testing.patch
text/x-patch
Filename: v1-0001-Add-pg_buffercache_evict_all-function-for-testing.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch v1-0001
Subject: Add pg_buffercache_evict_all() function for testing
| File | + | − |
|---|---|---|
| contrib/pg_buffercache/Makefile | 2 | 1 |
| contrib/pg_buffercache/meson.build | 1 | 0 |
| contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql | 7 | 0 |
| contrib/pg_buffercache/pg_buffercache.control | 1 | 1 |
| contrib/pg_buffercache/pg_buffercache_pages.c | 46 | 1 |
| doc/src/sgml/pgbuffercache.sgml | 20 | 2 |
| src/backend/storage/buffer/bufmgr.c | 4 | 1 |
| src/include/storage/bufmgr.h | 1 | 1 |
From 813e5ec0da4c65970b4b1ce2ec2918e4652da9ab Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <byavuz81@gmail.com>
Date: Fri, 20 Dec 2024 14:06:47 +0300
Subject: [PATCH v1 1/2] Add pg_buffercache_evict_all() function for testing
This new function provides a mechanism to evict all shared buffers at
once. It is designed to address the inefficiency of repeatedly calling
pg_buffercache_evict() for each individual buffer, which can be
time-consuming when dealing with large shared buffer pools
(e.g., ~790ms vs. ~270ms for 16GB of shared buffers).
It is intended for developer testing and debugging purposes and is
available to superusers only.
---
src/include/storage/bufmgr.h | 2 +-
src/backend/storage/buffer/bufmgr.c | 5 +-
doc/src/sgml/pgbuffercache.sgml | 22 ++++++++-
contrib/pg_buffercache/Makefile | 3 +-
contrib/pg_buffercache/meson.build | 1 +
.../pg_buffercache--1.5--1.6.sql | 7 +++
contrib/pg_buffercache/pg_buffercache.control | 2 +-
contrib/pg_buffercache/pg_buffercache_pages.c | 47 ++++++++++++++++++-
8 files changed, 82 insertions(+), 7 deletions(-)
create mode 100644 contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index eb0fba4230b..7f4eeca4afd 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -297,7 +297,7 @@ extern bool BgBufferSync(struct WritebackContext *wb_context);
extern void LimitAdditionalPins(uint32 *additional_pins);
extern void LimitAdditionalLocalPins(uint32 *additional_pins);
-extern bool EvictUnpinnedBuffer(Buffer buf);
+extern bool EvictUnpinnedBuffer(Buffer buf, bool *flushed);
/* in buf_init.c */
extern void BufferManagerShmemInit(void);
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 2622221809c..d2a93cf7cc0 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -6098,12 +6098,14 @@ ResOwnerPrintBufferPin(Datum res)
* or if the buffer becomes dirty again while we're trying to write it out.
*/
bool
-EvictUnpinnedBuffer(Buffer buf)
+EvictUnpinnedBuffer(Buffer buf, bool *flushed)
{
BufferDesc *desc;
uint32 buf_state;
bool result;
+ *flushed = false;
+
/* Make sure we can pin the buffer. */
ResourceOwnerEnlarge(CurrentResourceOwner);
ReservePrivateRefCountEntry();
@@ -6134,6 +6136,7 @@ EvictUnpinnedBuffer(Buffer buf)
LWLockAcquire(BufferDescriptorGetContentLock(desc), LW_SHARED);
FlushBuffer(desc, NULL, IOOBJECT_RELATION, IOCONTEXT_NORMAL);
LWLockRelease(BufferDescriptorGetContentLock(desc));
+ *flushed = true;
}
/* This will return false if it becomes dirty or someone else pins it. */
diff --git a/doc/src/sgml/pgbuffercache.sgml b/doc/src/sgml/pgbuffercache.sgml
index 4b90eefc0b0..df4d90a650a 100644
--- a/doc/src/sgml/pgbuffercache.sgml
+++ b/doc/src/sgml/pgbuffercache.sgml
@@ -31,8 +31,9 @@
This module provides the <function>pg_buffercache_pages()</function>
function (wrapped in the <structname>pg_buffercache</structname> view),
the <function>pg_buffercache_summary()</function> function, the
- <function>pg_buffercache_usage_counts()</function> function and
- the <function>pg_buffercache_evict()</function> function.
+ <function>pg_buffercache_usage_counts()</function> function, the
+ <function>pg_buffercache_evict()</function> and the
+ <function>pg_buffercache_evict_all()</function> function.
</para>
<para>
@@ -65,6 +66,12 @@
function is restricted to superusers only.
</para>
+ <para>
+ The <function>pg_buffercache_evict_all()</function> function tries to evict
+ all buffers in the buffer pool. It returns how many buffers are
+ evicted and flushed. Use of this function is restricted to superusers only.
+ </para>
+
<sect2 id="pgbuffercache-pg-buffercache">
<title>The <structname>pg_buffercache</structname> View</title>
@@ -378,6 +385,17 @@
</para>
</sect2>
+ <sect2 id="pgbuffercache-pg-buffercache-evict-all">
+ <title>The <structname>pg_buffercache_evict_all</structname> Function</title>
+ <para>
+ The <function>pg_buffercache_evict_all()</function> function is very similar
+ to <function>pg_buffercache_evict()</function> function. The difference is,
+ the <function>pg_buffercache_evict_all()</function> does not take argument;
+ instead it tries to evict all buffers in the buffer pool. The function is
+ intended for developer testing only.
+ </para>
+ </sect2>
+
<sect2 id="pgbuffercache-sample-output">
<title>Sample Output</title>
diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile
index eae65ead9e5..2a33602537e 100644
--- a/contrib/pg_buffercache/Makefile
+++ b/contrib/pg_buffercache/Makefile
@@ -8,7 +8,8 @@ OBJS = \
EXTENSION = pg_buffercache
DATA = pg_buffercache--1.2.sql pg_buffercache--1.2--1.3.sql \
pg_buffercache--1.1--1.2.sql pg_buffercache--1.0--1.1.sql \
- pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql
+ pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql \
+ pg_buffercache--1.5--1.6.sql
PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time"
REGRESS = pg_buffercache
diff --git a/contrib/pg_buffercache/meson.build b/contrib/pg_buffercache/meson.build
index 1ca3452918b..1ff57aa22e9 100644
--- a/contrib/pg_buffercache/meson.build
+++ b/contrib/pg_buffercache/meson.build
@@ -23,6 +23,7 @@ install_data(
'pg_buffercache--1.2.sql',
'pg_buffercache--1.3--1.4.sql',
'pg_buffercache--1.4--1.5.sql',
+ 'pg_buffercache--1.5--1.6.sql',
'pg_buffercache.control',
kwargs: contrib_data_args,
)
diff --git a/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql b/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql
new file mode 100644
index 00000000000..c08b799be94
--- /dev/null
+++ b/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql
@@ -0,0 +1,7 @@
+\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.6'" to load this file. \quit
+
+CREATE FUNCTION pg_buffercache_evict_all(
+ OUT buffers_evicted int4,
+ OUT buffers_flushed int4)
+AS 'MODULE_PATHNAME', 'pg_buffercache_evict_all'
+LANGUAGE C PARALLEL SAFE VOLATILE;
diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control
index 5ee875f77dd..b030ba3a6fa 100644
--- a/contrib/pg_buffercache/pg_buffercache.control
+++ b/contrib/pg_buffercache/pg_buffercache.control
@@ -1,5 +1,5 @@
# pg_buffercache extension
comment = 'examine the shared buffer cache'
-default_version = '1.5'
+default_version = '1.6'
module_pathname = '$libdir/pg_buffercache'
relocatable = true
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index 3ae0a018e10..ea7c0e6934c 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -19,6 +19,7 @@
#define NUM_BUFFERCACHE_PAGES_ELEM 9
#define NUM_BUFFERCACHE_SUMMARY_ELEM 5
#define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4
+#define NUM_BUFFERCACHE_EVICT_ALL_ELEM 2
PG_MODULE_MAGIC;
@@ -64,6 +65,7 @@ PG_FUNCTION_INFO_V1(pg_buffercache_pages);
PG_FUNCTION_INFO_V1(pg_buffercache_summary);
PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
PG_FUNCTION_INFO_V1(pg_buffercache_evict);
+PG_FUNCTION_INFO_V1(pg_buffercache_evict_all);
Datum
pg_buffercache_pages(PG_FUNCTION_ARGS)
@@ -356,6 +358,7 @@ Datum
pg_buffercache_evict(PG_FUNCTION_ARGS)
{
Buffer buf = PG_GETARG_INT32(0);
+ bool flushed;
if (!superuser())
ereport(ERROR,
@@ -365,5 +368,47 @@ pg_buffercache_evict(PG_FUNCTION_ARGS)
if (buf < 1 || buf > NBuffers)
elog(ERROR, "bad buffer ID: %d", buf);
- PG_RETURN_BOOL(EvictUnpinnedBuffer(buf));
+ PG_RETURN_BOOL(EvictUnpinnedBuffer(buf, &flushed));
+}
+
+/*
+ * Try to evict all shared buffers.
+ */
+Datum
+pg_buffercache_evict_all(PG_FUNCTION_ARGS)
+{
+ Datum result;
+ TupleDesc tupledesc;
+ HeapTuple tuple;
+ Datum values[NUM_BUFFERCACHE_EVICT_ALL_ELEM];
+ bool nulls[NUM_BUFFERCACHE_EVICT_ALL_ELEM] = {0};
+
+ int32 buffers_evicted = 0;
+ int32 buffers_flushed = 0;
+ bool flushed;
+
+ if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to use pg_buffercache_evict_all function")));
+
+ for (int buf = 1; buf < NBuffers; buf++)
+ {
+ if (EvictUnpinnedBuffer(buf, &flushed))
+ buffers_evicted++;
+ if (flushed)
+ buffers_flushed++;
+ }
+
+ values[0] = Int32GetDatum(buffers_evicted);
+ values[1] = Int32GetDatum(buffers_flushed);
+
+ /* Build and return the tuple. */
+ tuple = heap_form_tuple(tupledesc, values, nulls);
+ result = HeapTupleGetDatum(tuple);
+
+ PG_RETURN_DATUM(result);
}
--
2.45.2