Skip to content

Commit e91d2b5

Browse files
committed
introduce 'pathman_cache_stats' view, fix hash table memcontexts
1 parent 431c76b commit e91d2b5

File tree

8 files changed

+202
-15
lines changed

8 files changed

+202
-15
lines changed

init.sql

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,12 @@ LANGUAGE plpgsql;
250250
*/
251251
CREATE OR REPLACE FUNCTION @extschema@.show_partition_list()
252252
RETURNS TABLE (
253-
parent REGCLASS,
254-
partition REGCLASS,
255-
parttype INT4,
256-
partattr TEXT,
257-
range_min TEXT,
258-
range_max TEXT)
253+
parent REGCLASS,
254+
partition REGCLASS,
255+
parttype INT4,
256+
partattr TEXT,
257+
range_min TEXT,
258+
range_max TEXT)
259259
AS 'pg_pathman', 'show_partition_list_internal'
260260
LANGUAGE C STRICT;
261261

@@ -267,6 +267,23 @@ AS SELECT * FROM @extschema@.show_partition_list();
267267

268268
GRANT SELECT ON @extschema@.pathman_partition_list TO PUBLIC;
269269

270+
/*
271+
* Show memory usage of pg_pathman's caches.
272+
*/
273+
CREATE OR REPLACE FUNCTION @extschema@.show_cache_stats()
274+
RETURNS TABLE (
275+
context TEXT,
276+
size INT8,
277+
used INT8)
278+
AS 'pg_pathman', 'show_cache_stats_internal'
279+
LANGUAGE C STRICT;
280+
281+
/*
282+
* View for show_cache_stats().
283+
*/
284+
CREATE OR REPLACE VIEW @extschema@.pathman_cache_stats
285+
AS SELECT * FROM @extschema@.show_cache_stats();
286+
270287
/*
271288
* Show all existing concurrent partitioning tasks.
272289
*/

src/compat/relation_tags.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ rte_attach_tag(const uint32 query_id,
110110

111111
per_table_relation_tags = hash_create("Custom tags for RangeTblEntry",
112112
start_elems, &hashctl,
113-
HASH_ELEM | HASH_BLOBS);
113+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
114114
}
115115

116116
/* Search by 'htab_key' */

src/include/init.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef struct
3737
} PathmanInitState;
3838

3939

40+
#define PATHMAN_MCXT_COUNT 4
4041
extern MemoryContext TopPathmanContext;
4142
extern MemoryContext PathmanRelationCacheContext;
4243
extern MemoryContext PathmanParentCacheContext;
@@ -50,6 +51,31 @@ extern HTAB *constraint_cache;
5051
extern PathmanInitState pg_pathman_init_state;
5152

5253

54+
/* Transform pg_pathman's memory context into simple name */
55+
static inline const char *
56+
simpify_mcxt_name(MemoryContext mcxt)
57+
{
58+
static const char *top_mcxt = "maintenance";
59+
static const char *bound_mcxt = "bounds cache";
60+
static const char *parent_mcxt = "parents cache";
61+
static const char *constr_mcxt = "constraints cache";
62+
63+
if (mcxt == TopPathmanContext)
64+
return top_mcxt;
65+
66+
else if (mcxt == PathmanRelationCacheContext)
67+
return bound_mcxt;
68+
69+
else if (mcxt == PathmanParentCacheContext)
70+
return parent_mcxt;
71+
72+
else if (mcxt == PathmanCostraintCacheContext)
73+
return constr_mcxt;
74+
75+
else elog(ERROR, "error in function " CppAsString(simpify_mcxt_name));
76+
}
77+
78+
5379
/*
5480
* Check if pg_pathman is initialized.
5581
*/

src/include/pathman.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@
7575
#define Anum_pathman_pl_range_min 5 /* partition's min value */
7676
#define Anum_pathman_pl_range_max 6 /* partition's max value */
7777

78+
/*
79+
* Definitions for the "pathman_cache_stats" view.
80+
*/
81+
#define PATHMAN_CACHE_STATS "pathman_cache_stats"
82+
#define Natts_pathman_cache_stats 3
83+
#define Anum_pathman_cs_context 1 /* name of memory context */
84+
#define Anum_pathman_cs_size 2 /* size of memory context */
85+
#define Anum_pathman_cs_used 3 /* used space */
86+
7887

7988
/*
8089
* Cache current PATHMAN_CONFIG relid (set during load_config()).

src/include/utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "parser/parse_oper.h"
1919
#include "utils/rel.h"
2020
#include "nodes/relation.h"
21+
#include "nodes/memnodes.h"
2122
#include "nodes/nodeFuncs.h"
2223

2324

@@ -33,6 +34,9 @@ bool check_security_policy_internal(Oid relid, Oid role);
3334
*/
3435
Oid get_pathman_schema(void);
3536
List * list_reverse(List *l);
37+
void McxtStatsInternal(MemoryContext context, int level,
38+
bool examine_children,
39+
MemoryContextCounters *totals);
3640

3741
/*
3842
* Useful functions for relations.

src/init.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,25 +361,26 @@ init_local_cache(void)
361361
ctl.hcxt = PathmanRelationCacheContext;
362362

363363
partitioned_rels = hash_create("pg_pathman's partitioned relations cache",
364-
PART_RELS_SIZE, &ctl, HASH_ELEM | HASH_BLOBS);
364+
PART_RELS_SIZE, &ctl,
365+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
365366

366367
memset(&ctl, 0, sizeof(ctl));
367368
ctl.keysize = sizeof(Oid);
368369
ctl.entrysize = sizeof(PartParentInfo);
369370
ctl.hcxt = PathmanParentCacheContext;
370371

371372
parent_cache = hash_create("pg_pathman's partition parents cache",
372-
PART_RELS_SIZE * CHILD_FACTOR,
373-
&ctl, HASH_ELEM | HASH_BLOBS);
373+
PART_RELS_SIZE * CHILD_FACTOR, &ctl,
374+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
374375

375376
memset(&ctl, 0, sizeof(ctl));
376377
ctl.keysize = sizeof(Oid);
377378
ctl.entrysize = sizeof(PartConstraintInfo);
378379
ctl.hcxt = PathmanCostraintCacheContext;
379380

380381
constraint_cache = hash_create("pg_pathman's partition constraints cache",
381-
PART_RELS_SIZE * CHILD_FACTOR,
382-
&ctl, HASH_ELEM | HASH_BLOBS);
382+
PART_RELS_SIZE * CHILD_FACTOR, &ctl,
383+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
383384
}
384385

385386
/*

src/pl_funcs.c

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ PG_FUNCTION_INFO_V1( get_base_type_pl );
4646
PG_FUNCTION_INFO_V1( get_partition_key_type );
4747
PG_FUNCTION_INFO_V1( get_tablespace_pl );
4848

49+
PG_FUNCTION_INFO_V1( show_cache_stats_internal );
4950
PG_FUNCTION_INFO_V1( show_partition_list_internal );
5051

5152
PG_FUNCTION_INFO_V1( build_update_trigger_func_name );
@@ -72,9 +73,7 @@ PG_FUNCTION_INFO_V1( debug_capture );
7273
PG_FUNCTION_INFO_V1( get_pathman_lib_version );
7374

7475

75-
/*
76-
* User context for function show_partition_list_internal().
77-
*/
76+
/* User context for function show_partition_list_internal() */
7877
typedef struct
7978
{
8079
Relation pathman_config;
@@ -86,6 +85,13 @@ typedef struct
8685
uint32 child_number; /* child we're looking at */
8786
} show_partition_list_cxt;
8887

88+
/* User context for function show_pathman_cache_stats_internal() */
89+
typedef struct
90+
{
91+
MemoryContext pathman_contexts[PATHMAN_MCXT_COUNT];
92+
int current_context;
93+
} show_cache_stats_cxt;
94+
8995

9096
static void on_partitions_created_internal(Oid partitioned_table, bool add_callbacks);
9197
static void on_partitions_updated_internal(Oid partitioned_table, bool add_callbacks);
@@ -265,6 +271,92 @@ get_tablespace_pl(PG_FUNCTION_ARGS)
265271
* ----------------------
266272
*/
267273

274+
Datum
275+
show_cache_stats_internal(PG_FUNCTION_ARGS)
276+
{
277+
show_cache_stats_cxt *usercxt;
278+
FuncCallContext *funccxt;
279+
280+
/*
281+
* Initialize tuple descriptor & function call context.
282+
*/
283+
if (SRF_IS_FIRSTCALL())
284+
{
285+
TupleDesc tupdesc;
286+
MemoryContext old_mcxt;
287+
288+
funccxt = SRF_FIRSTCALL_INIT();
289+
290+
old_mcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
291+
292+
usercxt = (show_cache_stats_cxt *) palloc(sizeof(show_cache_stats_cxt));
293+
294+
usercxt->pathman_contexts[0] = TopPathmanContext;
295+
usercxt->pathman_contexts[1] = PathmanRelationCacheContext;
296+
usercxt->pathman_contexts[2] = PathmanParentCacheContext;
297+
usercxt->pathman_contexts[3] = PathmanCostraintCacheContext;
298+
299+
usercxt->current_context = 0;
300+
301+
/* Create tuple descriptor */
302+
tupdesc = CreateTemplateTupleDesc(Natts_pathman_cache_stats, false);
303+
304+
TupleDescInitEntry(tupdesc, Anum_pathman_cs_context,
305+
"context", TEXTOID, -1, 0);
306+
TupleDescInitEntry(tupdesc, Anum_pathman_cs_size,
307+
"size", INT8OID, -1, 0);
308+
TupleDescInitEntry(tupdesc, Anum_pathman_cs_used,
309+
"used", INT8OID, -1, 0);
310+
311+
funccxt->tuple_desc = BlessTupleDesc(tupdesc);
312+
funccxt->user_fctx = (void *) usercxt;
313+
314+
MemoryContextSwitchTo(old_mcxt);
315+
}
316+
317+
funccxt = SRF_PERCALL_SETUP();
318+
usercxt = (show_cache_stats_cxt *) funccxt->user_fctx;
319+
320+
if (usercxt->current_context < lengthof(usercxt->pathman_contexts))
321+
{
322+
MemoryContext current_mcxt;
323+
MemoryContextCounters mcxt_stats;
324+
HeapTuple htup;
325+
Datum values[Natts_pathman_cache_stats];
326+
bool isnull[Natts_pathman_cache_stats] = { 0 };
327+
328+
/* Prepare context counters */
329+
memset(&mcxt_stats, 0, sizeof(mcxt_stats));
330+
331+
/* Select current memory context */
332+
current_mcxt = usercxt->pathman_contexts[usercxt->current_context];
333+
334+
/* NOTE: we do not consider child contexts if it's TopPathmanContext */
335+
McxtStatsInternal(current_mcxt, 0,
336+
(current_mcxt != TopPathmanContext),
337+
&mcxt_stats);
338+
339+
values[Anum_pathman_cs_context - 1] =
340+
CStringGetTextDatum(simpify_mcxt_name(current_mcxt));
341+
342+
values[Anum_pathman_cs_size - 1] =
343+
Int64GetDatum(mcxt_stats.totalspace);
344+
345+
values[Anum_pathman_cs_used - 1] =
346+
Int64GetDatum(mcxt_stats.totalspace - mcxt_stats.freespace);
347+
348+
/* Switch to next context */
349+
usercxt->current_context++;
350+
351+
/* Form output tuple */
352+
htup = heap_form_tuple(funccxt->tuple_desc, values, isnull);
353+
354+
SRF_RETURN_NEXT(funccxt, HeapTupleGetDatum(htup));
355+
}
356+
357+
SRF_RETURN_DONE(funccxt);
358+
}
359+
268360
/*
269361
* List all existing partitions and their parents.
270362
*/

src/utils.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* definitions of various support functions
55
*
66
* Copyright (c) 2016, Postgres Professional
7+
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
79
*
810
* ------------------------------------------------------------------------
911
*/
@@ -162,6 +164,42 @@ list_reverse(List *l)
162164
return result;
163165
}
164166

167+
void
168+
McxtStatsInternal(MemoryContext context, int level,
169+
bool examine_children,
170+
MemoryContextCounters *totals)
171+
{
172+
MemoryContextCounters local_totals;
173+
MemoryContext child;
174+
175+
AssertArg(MemoryContextIsValid(context));
176+
177+
/* Examine the context itself */
178+
(*context->methods->stats) (context, level, false, totals);
179+
180+
memset(&local_totals, 0, sizeof(local_totals));
181+
182+
if (!examine_children)
183+
return;
184+
185+
/* Examine children */
186+
for (child = context->firstchild;
187+
child != NULL;
188+
child = child->nextchild)
189+
{
190+
191+
McxtStatsInternal(child, level + 1,
192+
examine_children,
193+
&local_totals);
194+
}
195+
196+
/* Save children stats */
197+
totals->nblocks += local_totals.nblocks;
198+
totals->freechunks += local_totals.freechunks;
199+
totals->totalspace += local_totals.totalspace;
200+
totals->freespace += local_totals.freespace;
201+
}
202+
165203

166204

167205
/*

0 commit comments

Comments
 (0)