trimheapfreemeory.patch
application/octet-stream
Filename: trimheapfreemeory.patch
Type: application/octet-stream
Part: 0
Message:
Trim the heap free memory
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/system_functions.sql | 2 | 0 |
| src/backend/postmaster/autovacuum.c | 4 | 0 |
| src/backend/postmaster/checkpointer.c | 4 | 0 |
| src/backend/postmaster/interrupt.c | 4 | 0 |
| src/backend/postmaster/pgarch.c | 4 | 0 |
| src/backend/postmaster/startup.c | 4 | 0 |
| src/backend/postmaster/walsummarizer.c | 4 | 0 |
| src/backend/storage/ipc/procsignal.c | 3 | 0 |
| src/backend/tcop/postgres.c | 3 | 0 |
| src/backend/utils/adt/mcxtfuncs.c | 54 | 0 |
| src/backend/utils/init/globals.c | 1 | 0 |
| src/backend/utils/mmgr/Makefile | 1 | 0 |
| src/include/catalog/pg_proc.dat | 6 | 0 |
| src/include/miscadmin.h | 2 | 0 |
| src/include/storage/procsignal.h | 2 | 0 |
| src/include/utils/memutils.h | 3 | 0 |
| src/test/regress/expected/misc_functions.out | 11 | 0 |
| src/test/regress/sql/misc_functions.sql | 8 | 0 |
diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql
index 623b9539b1..3aa3b60288 100644
--- a/src/backend/catalog/system_functions.sql
+++ b/src/backend/catalog/system_functions.sql
@@ -754,6 +754,8 @@ REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_trim_backend_heap_free_memory(integer) FROM PUBLIC;
+
REVOKE EXECUTE ON FUNCTION pg_ls_logicalsnapdir() FROM PUBLIC;
REVOKE EXECUTE ON FUNCTION pg_ls_logicalmapdir() FROM PUBLIC;
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 7d0877c95e..d90d1649a1 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -765,6 +765,10 @@ HandleAutoVacLauncherInterrupts(void)
if (LogMemoryContextPending)
ProcessLogMemoryContextInterrupt();
+ /* Perform trimming heap free memory of this process */
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
+
/* Process sinval catchup interrupts that happened while sleeping */
ProcessCatchupInterrupt();
}
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 199f008bcd..2109f9e822 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -605,6 +605,10 @@ HandleCheckpointerInterrupts(void)
/* Perform logging of memory contexts of this process */
if (LogMemoryContextPending)
ProcessLogMemoryContextInterrupt();
+
+ /* Perform trimming heap free memory of this process */
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
}
/*
diff --git a/src/backend/postmaster/interrupt.c b/src/backend/postmaster/interrupt.c
index eedc0980cf..4389ff3d48 100644
--- a/src/backend/postmaster/interrupt.c
+++ b/src/backend/postmaster/interrupt.c
@@ -48,6 +48,10 @@ HandleMainLoopInterrupts(void)
/* Perform logging of memory contexts of this process */
if (LogMemoryContextPending)
ProcessLogMemoryContextInterrupt();
+
+ /* Perform trimming heap free memory of this process */
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
}
/*
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 02f91431f5..cd72412614 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -865,6 +865,10 @@ HandlePgArchInterrupts(void)
if (LogMemoryContextPending)
ProcessLogMemoryContextInterrupt();
+ /* Perform trimming heap free memory of this process */
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
+
if (ConfigReloadPending)
{
char *archiveLib = pstrdup(XLogArchiveLibrary);
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
index ef6f98ebcd..5eb8d168e7 100644
--- a/src/backend/postmaster/startup.c
+++ b/src/backend/postmaster/startup.c
@@ -192,6 +192,10 @@ HandleStartupProcInterrupts(void)
/* Perform logging of memory contexts of this process */
if (LogMemoryContextPending)
ProcessLogMemoryContextInterrupt();
+
+ /* Perform trimming heap free memory of this process */
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
}
diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c
index daa7909382..d167e41291 100644
--- a/src/backend/postmaster/walsummarizer.c
+++ b/src/backend/postmaster/walsummarizer.c
@@ -874,6 +874,10 @@ HandleWalSummarizerInterrupts(void)
/* Perform logging of memory contexts of this process */
if (LogMemoryContextPending)
ProcessLogMemoryContextInterrupt();
+
+ /* Perform trimming heap free memory of this process */
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
}
/*
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
index 87027f27eb..3251d2823e 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -712,6 +712,9 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN))
HandleRecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
+ if (CheckProcSignal(PROCSIG_TRIM_HEAP_FREE_MEMORY))
+ HandleTrimHeapFreeMemoryInterrupt();
+
SetLatch(MyLatch);
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 8bc6bea113..f90a557bbe 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3479,6 +3479,9 @@ ProcessInterrupts(void)
if (ParallelApplyMessagePending)
HandleParallelApplyMessages();
+
+ if (TrimHeapFreeMemoryPending)
+ ProcessTrimHeapFreeMemoryInterrupt();
}
/*
diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c
index 6a6634e1cd..c213c4163a 100644
--- a/src/backend/utils/adt/mcxtfuncs.c
+++ b/src/backend/utils/adt/mcxtfuncs.c
@@ -305,3 +305,57 @@ pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(true);
}
+
+/*
+ * pg_trim_backend_heap_free_memory
+ * Signal a backend or an auxiliary process to trim heap free memory.
+ *
+ * On receipt of this signal, a backend or an auxiliary process sets the flag
+ * in the signal handler, which causes the next CHECK_FOR_INTERRUPTS()
+ * or process-specific interrupt handler to log the memory contexts.
+ */
+Datum
+pg_trim_backend_heap_free_memory(PG_FUNCTION_ARGS)
+{
+ int pid = PG_GETARG_INT32(0);
+ PGPROC *proc;
+ ProcNumber procNumber = INVALID_PROC_NUMBER;
+
+ /*
+ * See if the process with given pid is a backend or an auxiliary process.
+ */
+ proc = BackendPidGetProc(pid);
+ if (proc == NULL)
+ proc = AuxiliaryPidGetProc(pid);
+
+ /*
+ * BackendPidGetProc() and AuxiliaryPidGetProc() return NULL if the pid
+ * isn't valid; but by the time we reach kill(), a process for which we
+ * get a valid proc here might have terminated on its own. There's no way
+ * to acquire a lock on an arbitrary process to prevent that. But since
+ * this mechanism is usually used to debug a backend or an auxiliary
+ * process running and consuming lots of memory, that it might end on its
+ * own first and its memory contexts are not logged is not a problem.
+ */
+ if (proc == NULL)
+ {
+ /*
+ * This is just a warning so a loop-through-resultset will not abort
+ * if one backend terminated on its own during the run.
+ */
+ ereport(WARNING,
+ (errmsg("PID %d is not a PostgreSQL server process", pid)));
+ PG_RETURN_BOOL(false);
+ }
+
+ procNumber = GetNumberFromPGProc(proc);
+ if (SendProcSignal(pid, PROCSIG_TRIM_HEAP_FREE_MEMORY, procNumber) < 0)
+ {
+ /* Again, just a warning to allow loops */
+ ereport(WARNING,
+ (errmsg("could not send signal to process %d: %m", pid)));
+ PG_RETURN_BOOL(false);
+ }
+
+ PG_RETURN_BOOL(true);
+}
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 03a54451ac..e90a61affe 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -39,6 +39,7 @@ volatile sig_atomic_t IdleSessionTimeoutPending = false;
volatile sig_atomic_t ProcSignalBarrierPending = false;
volatile sig_atomic_t LogMemoryContextPending = false;
volatile sig_atomic_t IdleStatsUpdateTimeoutPending = false;
+volatile sig_atomic_t TrimHeapFreeMemoryPending = false;
volatile uint32 InterruptHoldoffCount = 0;
volatile uint32 QueryCancelHoldoffCount = 0;
volatile uint32 CritSectionCount = 0;
diff --git a/src/backend/utils/mmgr/Makefile b/src/backend/utils/mmgr/Makefile
index 01a1fb8527..395f119d77 100644
--- a/src/backend/utils/mmgr/Makefile
+++ b/src/backend/utils/mmgr/Makefile
@@ -21,6 +21,7 @@ OBJS = \
generation.o \
mcxt.o \
memdebug.o \
+ memtrim.o \
portalmem.o \
slab.o
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4abc6d9526..6186d9247d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8348,6 +8348,12 @@
prorettype => 'bool', proargtypes => 'int4',
prosrc => 'pg_log_backend_memory_contexts' },
+# logging memory contexts of the specified backend
+{ oid => '4551', descr => 'Trim Heap free memory of the specified backend',
+ proname => 'pg_trim_backend_heap_free_memory', provolatile => 'v',
+ prorettype => 'bool', proargtypes => 'int4',
+ prosrc => 'pg_trim_backend_heap_free_memory' },
+
# non-persistent series generator
{ oid => '1066', descr => 'non-persistent series generator',
proname => 'generate_series', prorows => '1000',
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 25348e71eb..5a676eeb9e 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -100,6 +100,8 @@ extern PGDLLIMPORT volatile sig_atomic_t IdleStatsUpdateTimeoutPending;
extern PGDLLIMPORT volatile sig_atomic_t CheckClientConnectionPending;
extern PGDLLIMPORT volatile sig_atomic_t ClientConnectionLost;
+extern PGDLLIMPORT volatile sig_atomic_t TrimHeapFreeMemoryPending;
+
/* these are marked volatile because they are examined by signal handlers: */
extern PGDLLIMPORT volatile uint32 InterruptHoldoffCount;
extern PGDLLIMPORT volatile uint32 QueryCancelHoldoffCount;
diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h
index f94c11a9a8..0d4a3a42a2 100644
--- a/src/include/storage/procsignal.h
+++ b/src/include/storage/procsignal.h
@@ -48,6 +48,8 @@ typedef enum
PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK,
PROCSIG_RECOVERY_CONFLICT_LAST = PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK,
+ PROCSIG_TRIM_HEAP_FREE_MEMORY, /* ask backend to release free memory from the heap */
+
NUM_PROCSIGNALS /* Must be last! */
} ProcSignalReason;
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index cd9596ff21..61d4d6d252 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -104,6 +104,9 @@ extern void MemoryContextCheck(MemoryContext context);
extern void HandleLogMemoryContextInterrupt(void);
extern void ProcessLogMemoryContextInterrupt(void);
+extern void HandleTrimHeapFreeMemoryInterrupt(void);
+extern void ProcessTrimHeapFreeMemoryInterrupt(void);
+
/*
* Memory-context-type-specific functions
*/
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index 35fb72f302..9bde10b2b1 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -365,6 +365,17 @@ RESET ROLE;
REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer)
FROM regress_log_memory;
DROP ROLE regress_log_memory;
+--
+-- pg_trim_backend_heap_free_memory()
+--
+-- Trim the heap free memory.
+--
+SELECT pg_trim_backend_heap_free_memory(pg_backend_pid());
+ pg_trim_backend_heap_free_memory
+----------------------------------
+ t
+(1 row)
+
--
-- Test some built-in SRFs
--
diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql
index e570783453..d1cd2440ee 100644
--- a/src/test/regress/sql/misc_functions.sql
+++ b/src/test/regress/sql/misc_functions.sql
@@ -143,6 +143,14 @@ REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer)
DROP ROLE regress_log_memory;
+--
+-- pg_trim_backend_heap_free_memory()
+--
+-- Trim the heap free memory.
+--
+
+SELECT pg_trim_backend_heap_free_memory(pg_backend_pid());
+
--
-- Test some built-in SRFs
--