Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-cloudberry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ jobs:
"contrib/pgcrypto:installcheck",
"contrib/tablefunc:installcheck",
"contrib/passwordcheck:installcheck",
"contrib/pg_buffercache:installcheck",
"contrib/sslinfo:installcheck"]
},
{"test":"ic-gpcontrib",
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build-deb-cloudberry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ jobs:
"contrib/pgcrypto:installcheck",
"contrib/tablefunc:installcheck",
"contrib/passwordcheck:installcheck",
"contrib/pg_buffercache:installcheck",
"contrib/sslinfo:installcheck"]
},
{"test":"ic-deb-gpcontrib",
Expand Down
28 changes: 16 additions & 12 deletions contrib/pg_buffercache/expected/pg_buffercache.out
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,24 @@ from pg_buffercache_summary();
t | t | t
(1 row)

SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;
?column?
----------
t
(1 row)

-- Check that the functions / views can't be accessed by default. To avoid
-- having to create a dedicated user, use the pg_database_owner pseudo-role.
SET ROLE pg_database_owner;
SELECT * FROM pg_buffercache;
ERROR: permission denied for view pg_buffercache
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
ERROR: permission denied for function pg_buffercache_pages
SELECT * FROM pg_buffercache_summary();
ERROR: permission denied for function pg_buffercache_summary
SELECT * FROM pg_buffercache_usage_counts();
ERROR: permission denied for function pg_buffercache_usage_counts
RESET role;
SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;
?column?
----------
Expand Down Expand Up @@ -72,17 +87,7 @@ SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated WHERE buffers >=
(1 row)

-- Check that the functions / views can't be accessed by default.
CREATE ROLE buffercache_test;
SET ROLE buffercache_test;
SELECT * FROM pg_buffercache;
ERROR: permission denied for view pg_buffercache
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
ERROR: permission denied for function pg_buffercache_pages
SELECT * FROM pg_buffercache_summary();
ERROR: permission denied for function pg_buffercache_summary
RESET role;
SELECT * FROM pg_buffercache_usage_counts();
ERROR: permission denied for function pg_buffercache_usage_counts
SET ROLE pg_database_owner;
-- GPDB
SELECT * FROM pg_buffercache_summary;
ERROR: permission denied for view pg_buffercache_summary
Expand Down Expand Up @@ -166,4 +171,3 @@ SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated;
(1 row)

RESET ROLE;
DROP ROLE buffercache_test;
11 changes: 11 additions & 0 deletions contrib/pg_buffercache/pg_buffercache--1.3--1.4.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ CREATE FUNCTION pg_buffercache_summary(
AS 'MODULE_PATHNAME', 'pg_buffercache_summary'
LANGUAGE C PARALLEL SAFE;

CREATE FUNCTION pg_buffercache_usage_counts(
OUT usage_count int4,
OUT buffers int4,
OUT dirty int4,
OUT pinned int4)
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pg_buffercache_usage_counts'
LANGUAGE C PARALLEL SAFE;

-- Don't want these to be available to public.
REVOKE ALL ON FUNCTION pg_buffercache_summary() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION pg_buffercache_summary() TO pg_monitor;
REVOKE ALL ON FUNCTION pg_buffercache_usage_counts() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION pg_buffercache_usage_counts() TO pg_monitor;
43 changes: 43 additions & 0 deletions contrib/pg_buffercache/pg_buffercache_pages.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define NUM_BUFFERCACHE_PAGES_MIN_ELEM 8
#define NUM_BUFFERCACHE_PAGES_ELEM 9
#define NUM_BUFFERCACHE_SUMMARY_ELEM 5
#define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4

PG_MODULE_MAGIC;

Expand Down Expand Up @@ -61,6 +62,7 @@ typedef struct
*/
PG_FUNCTION_INFO_V1(pg_buffercache_pages);
PG_FUNCTION_INFO_V1(pg_buffercache_summary);
PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);

Datum
pg_buffercache_pages(PG_FUNCTION_ARGS)
Expand Down Expand Up @@ -304,3 +306,44 @@ pg_buffercache_summary(PG_FUNCTION_ARGS)

PG_RETURN_DATUM(result);
}

Datum
pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
int usage_counts[BM_MAX_USAGE_COUNT + 1] = {0};
int dirty[BM_MAX_USAGE_COUNT + 1] = {0};
int pinned[BM_MAX_USAGE_COUNT + 1] = {0};
Datum values[NUM_BUFFERCACHE_USAGE_COUNTS_ELEM];
bool nulls[NUM_BUFFERCACHE_USAGE_COUNTS_ELEM] = {0};

InitMaterializedSRF(fcinfo, 0);

for (int i = 0; i < NBuffers; i++)
{
BufferDesc *bufHdr = GetBufferDescriptor(i);
uint32 buf_state = pg_atomic_read_u32(&bufHdr->state);
int usage_count;

usage_count = BUF_STATE_GET_USAGECOUNT(buf_state);
usage_counts[usage_count]++;

if (buf_state & BM_DIRTY)
dirty[usage_count]++;

if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
pinned[usage_count]++;
}

for (int i = 0; i < BM_MAX_USAGE_COUNT + 1; i++)
{
values[0] = Int32GetDatum(i);
values[1] = Int32GetDatum(usage_counts[i]);
values[2] = Int32GetDatum(dirty[i]);
values[3] = Int32GetDatum(pinned[i]);

tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}

return (Datum) 0;
}
12 changes: 4 additions & 8 deletions contrib/pg_buffercache/sql/pg_buffercache.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ select buffers_used + buffers_unused > 0,
buffers_pinned <= buffers_used
from pg_buffercache_summary();

SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;

-- Check that the functions / views can't be accessed by default. To avoid
-- having to create a dedicated user, use the pg_database_owner pseudo-role.
SET ROLE pg_database_owner;
SELECT * FROM pg_buffercache;
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
SELECT * FROM pg_buffercache_summary();
SELECT * FROM pg_buffercache_usage_counts();
RESET role;
SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;

Expand All @@ -42,12 +45,7 @@ SELECT count(*) > 0 FROM gp_buffercache_usage_counts WHERE buffers >= 0;
SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated WHERE buffers >= 0;

-- Check that the functions / views can't be accessed by default.
CREATE ROLE buffercache_test;
SET ROLE buffercache_test;
SELECT * FROM pg_buffercache;
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
SELECT * FROM pg_buffercache_summary();
SELECT * FROM pg_buffercache_usage_counts();
SET ROLE pg_database_owner;
-- GPDB
SELECT * FROM pg_buffercache_summary;
SELECT * FROM pg_buffercache_usage_counts;
Expand All @@ -73,5 +71,3 @@ SELECT buffers_used + buffers_unused > 0 FROM gp_buffercache_summary_aggregated;
SELECT count(*) > 0 FROM gp_buffercache_usage_counts;
SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated;
RESET ROLE;

DROP ROLE buffercache_test;
105 changes: 101 additions & 4 deletions doc/src/sgml/pgbuffercache.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
</indexterm>

<para>
The module provides the <function>pg_buffercache_pages()</function>
function, wrapped in the <structname>pg_buffercache</structname> view, and
the <function>pg_buffercache_summary()</function> function.
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, and the
<function>pg_buffercache_usage_counts()</function> function.
</para>

<para>
Expand All @@ -38,6 +39,12 @@
row summarizing the state of the shared buffer cache.
</para>

<para>
The <function>pg_buffercache_usage_counts()</function> function returns a set
of records, each row describing the number of buffers with a given usage
count.
</para>

<para>
By default, use is restricted to superusers and roles with privileges of the
<literal>pg_monitor</literal> role. Access may be granted to others
Expand Down Expand Up @@ -242,7 +249,7 @@
<structfield>usagecount_avg</structfield> <type>float8</type>
</para>
<para>
Average usagecount of used shared buffers
Average usage count of used shared buffers
</para></entry>
</row>
</tbody>
Expand All @@ -266,6 +273,84 @@
</sect2>

<sect2>
<title>The <function>pg_buffercache_usage_counts()</function> Function</title>

<para>
The definitions of the columns exposed by the function are shown in
<xref linkend="pgbuffercache_usage_counts-columns"/>.
</para>

<table id="pgbuffercache_usage_counts-columns">
<title><function>pg_buffercache_usage_counts()</function> Output Columns</title>
<tgroup cols="1">
<thead>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
Column Type
</para>
<para>
Description
</para></entry>
</row>
</thead>

<tbody>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>usage_count</structfield> <type>int4</type>
</para>
<para>
A possible buffer usage count
</para></entry>
</row>

<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>buffers</structfield> <type>int4</type>
</para>
<para>
Number of buffers with the usage count
</para></entry>
</row>

<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>dirty</structfield> <type>int4</type>
</para>
<para>
Number of dirty buffers with the usage count
</para></entry>
</row>

<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>pinned</structfield> <type>int4</type>
</para>
<para>
Number of pinned buffers with the usage count
</para></entry>
</row>
</tbody>
</tgroup>
</table>

<para>
The <function>pg_buffercache_usage_counts()</function> function returns a
set of rows summarizing the states of all shared buffers, aggregated over
the possible usage count values. Similar and more detailed information is
provided by the <structname>pg_buffercache</structname> view, but
<function>pg_buffercache_usage_counts()</function> is significantly cheaper.
</para>

<para>
Like the <structname>pg_buffercache</structname> view,
<function>pg_buffercache_usage_counts()</function> does not acquire buffer
manager locks. Therefore concurrent activity can lead to minor inaccuracies
in the result.
</para>
</sect2>

<sect2 id="pgbuffercache-sample-output">
<title>Sample Output</title>

<screen>
Expand Down Expand Up @@ -299,6 +384,18 @@ regression=# SELECT * FROM pg_buffercache_summary();
--------------+----------------+---------------+----------------+----------------
248 | 2096904 | 39 | 0 | 3.141129
(1 row)


regression=# SELECT * FROM pg_buffercache_usage_counts();
usage_count | buffers | dirty | pinned
-------------+---------+-------+--------
0 | 14650 | 0 | 0
1 | 1436 | 671 | 0
2 | 102 | 88 | 0
3 | 23 | 21 | 0
4 | 9 | 7 | 0
5 | 164 | 106 | 0
(6 rows)
</screen>
</sect2>

Expand Down
Loading