Display Pg buffer cache (WIP) - Mailing list pgsql-patches
| From | Mark Kirkwood |
|---|---|
| Subject | Display Pg buffer cache (WIP) |
| Date | |
| Msg-id | 4226A244.7000100@coretech.co.nz Whole thread Raw |
| Responses |
Re: Display Pg buffer cache (WIP)
|
| List | pgsql-patches |
I found it useful to be able to look at what relations are occupying the
cache (mainly for debugging and comparing with page estimates).
I am wondering if it might be a useful addition generally?
How it works a SRF called dump_cache() is created, which is then exposed
as system view pg_dump_cache. So stuff like the following can be
performed (cache of 2000 immediately after 'make installcheck'):
regression=# SELECT c.relname, count(*) AS buffers
regression-# FROM pg_class c, pg_dump_cache d
regression-# WHERE d.relfilenode = c.relfilenode
regression-# GROUP BY c.relname
regression-# ORDER BY 2 DESC LIMIT 10;
relname | buffers
---------------------------------+---------
tenk1 | 345
tenk2 | 345
onek | 138
pg_attribute | 102
road | 81
pg_attribute_relid_attnam_index | 74
onek2 | 69
pg_proc | 59
pg_proc_proname_args_nsp_index | 56
hash_f8_heap | 49
(10 rows)
regression=#
As of now the patch breaks 1 regression test (rules - that new view...)
and does not peek into the contents of the buffers themselves (I was
mainly interested in which relations were there), and does not worry too
much about a consistent view of the buffer contents (as I didn't want it
to block all other activity!).
If it seems like a worthwhile addition I will amend the regression
expected and resubmit.
Any comments?
Mark
diff -Naur pgsql.orig/src/backend/catalog/system_views.sql pgsql/src/backend/catalog/system_views.sql
--- pgsql.orig/src/backend/catalog/system_views.sql Thu Mar 3 11:29:55 2005
+++ pgsql/src/backend/catalog/system_views.sql Thu Mar 3 11:41:24 2005
@@ -277,3 +277,8 @@
DO INSTEAD NOTHING;
GRANT SELECT, UPDATE ON pg_settings TO PUBLIC;
+
+CREATE VIEW pg_dump_cache AS
+ SELECT D.* FROM pg_dump_cache() AS D
+ (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid);
+
diff -Naur pgsql.orig/src/backend/utils/adt/Makefile pgsql/src/backend/utils/adt/Makefile
--- pgsql.orig/src/backend/utils/adt/Makefile Thu Mar 3 11:29:53 2005
+++ pgsql/src/backend/utils/adt/Makefile Thu Mar 3 11:32:10 2005
@@ -24,7 +24,7 @@
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
network.o mac.o inet_net_ntop.o inet_net_pton.o \
ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
- ascii.o quote.o pgstatfuncs.o encode.o
+ ascii.o quote.o pgstatfuncs.o encode.o dumpcache.o
like.o: like.c like_match.c
diff -Naur pgsql.orig/src/backend/utils/adt/dumpcache.c pgsql/src/backend/utils/adt/dumpcache.c
--- pgsql.orig/src/backend/utils/adt/dumpcache.c Thu Jan 1 12:00:00 1970
+++ pgsql/src/backend/utils/adt/dumpcache.c Thu Mar 3 11:51:53 2005
@@ -0,0 +1,119 @@
+/*-------------------------------------------------------------------------
+ *
+ * dumpcache.c
+ * display some contents for the buffer cache
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+#include "funcapi.h"
+#include "catalog/pg_type.h"
+#include "storage/buf_internals.h"
+#include "storage/bufmgr.h"
+#include "utils/relcache.h"
+
+
+extern Datum dump_cache(PG_FUNCTION_ARGS);
+
+
+/*
+ * Function context for data persisting over repeated calls.
+ */
+typedef struct {
+ int buffer;
+ AttInMetadata *attinmeta;
+ BufferDesc *bufhdr;
+ RelFileNode rnode;
+ char *values[3];
+} dumpcache_fctx;
+
+
+/*
+ * Return a tuple that has bufferid, relfilenoide, reltablespace and
+ * reldatabase OIDs.
+ */
+Datum
+dump_cache(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ Datum result;
+ MemoryContext oldcontext;
+ dumpcache_fctx *fctx; /* User function context. */
+ TupleDesc tupledesc;
+ HeapTuple tuple;
+
+ if (SRF_IS_FIRSTCALL())
+ {
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* Switch context when allocating stuff to be used in later calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ /* construct a tuple to return */
+ tupledesc = CreateTemplateTupleDesc(4, false);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 3, "reltablespace",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupledesc, (AttrNumber) 4, "reldatabase",
+ OIDOID, -1, 0);
+
+ /* Generate attribute metadata needed later to produce tuples */
+ funcctx->attinmeta = TupleDescGetAttInMetadata(tupledesc);
+
+ /*
+ * Create a function context for cross-call persistence
+ * and initialize the buffer counters.
+ */
+ fctx = (dumpcache_fctx *) palloc(sizeof(dumpcache_fctx));
+
+ fctx->buffer = 0;
+ fctx->bufhdr = BufferDescriptors;
+
+ funcctx->user_fctx = fctx;
+ funcctx->max_calls = NBuffers;
+
+ /* allocate the strings for tuple formation */
+ fctx->values[0] = (char *) palloc(NAMEDATALEN + 1);
+ fctx->values[1] = (char *) palloc(NAMEDATALEN + 1);
+ fctx->values[2] = (char *) palloc(NAMEDATALEN + 1);
+ fctx->values[3] = (char *) palloc(NAMEDATALEN + 1);
+
+
+ /* Return to original context when allocating transient memory */
+ MemoryContextSwitchTo(oldcontext);
+ }
+ /* <user defined code> */
+ funcctx = SRF_PERCALL_SETUP();
+
+ /* Get the saved state, and set up the result */
+ fctx = funcctx->user_fctx;
+
+
+ if (funcctx->call_cntr < funcctx->max_calls)
+ {
+ /* Get the relation node */
+ fctx->rnode = (fctx->bufhdr)->tag.rnode;
+
+ /* setup cstrings and create a tuple from them */
+ sprintf(fctx->values[0], "%u", fctx->buffer);
+ sprintf(fctx->values[1], "%u", fctx->rnode.relNode);
+ sprintf(fctx->values[2], "%u", fctx->rnode.spcNode);
+ sprintf(fctx->values[3], "%u", fctx->rnode.dbNode);
+
+ tuple = BuildTupleFromCStrings(funcctx->attinmeta, fctx->values);
+ result = HeapTupleGetDatum(tuple);
+
+
+ /* increment the buffer count and the buffer it points to */
+ fctx->buffer++;
+ fctx->bufhdr++;
+
+ SRF_RETURN_NEXT(funcctx, result);
+ }
+ else
+ SRF_RETURN_DONE(funcctx);
+}
+
diff -Naur pgsql.orig/src/include/catalog/pg_proc.h pgsql/src/include/catalog/pg_proc.h
--- pgsql.orig/src/include/catalog/pg_proc.h Thu Mar 3 11:30:02 2005
+++ pgsql/src/include/catalog/pg_proc.h Thu Mar 3 11:39:27 2005
@@ -3615,6 +3615,8 @@
DATA(insert OID = 2558 ( int4 PGNSP PGUID 12 f f t f i 1 23 "16" _null_ bool_int4 - _null_ ));
DESCR("convert boolean to int4");
+/* dump cache */
+DATA(insert OID = 2510 ( pg_dump_cache PGNSP PGUID 12 f f t t v 0 2249 "" _null_ dump_cache - _null_ ));
/*
* Symbolic values for provolatile column: these indicate whether the result
pgsql-patches by date: