1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* mcxt.c
|
2000-06-28 05:33:33 +02:00
|
|
|
* POSTGRES memory context management code.
|
|
|
|
*
|
|
|
|
* This module handles context management operations that are independent
|
|
|
|
* of the particular kind of context being operated on. It calls
|
|
|
|
* context-type-specific operations via the function pointers in a
|
|
|
|
* context's MemoryContextMethods struct.
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2019-01-02 18:44:25 +01:00
|
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/utils/mmgr/mcxt.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
2012-10-08 22:34:33 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
#include "mb/pg_wchar.h"
|
2014-04-04 13:27:18 +02:00
|
|
|
#include "miscadmin.h"
|
2013-06-27 02:00:08 +02:00
|
|
|
#include "utils/memdebug.h"
|
2000-06-28 05:33:33 +02:00
|
|
|
#include "utils/memutils.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-07 07:04:48 +02:00
|
|
|
* GLOBAL MEMORY *
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* CurrentMemoryContext
|
2000-06-28 05:33:33 +02:00
|
|
|
* Default memory context for allocations.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2001-01-12 00:27:05 +01:00
|
|
|
MemoryContext CurrentMemoryContext = NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
This patch implements holdable cursors, following the proposal
(materialization into a tuple store) discussed on pgsql-hackers earlier.
I've updated the documentation and the regression tests.
Notes on the implementation:
- I needed to change the tuple store API slightly -- it assumes that it
won't be used to hold data across transaction boundaries, so the temp
files that it uses for on-disk storage are automatically reclaimed at
end-of-transaction. I added a flag to tuplestore_begin_heap() to control
this behavior. Is changing the tuple store API in this fashion OK?
- in order to store executor results in a tuple store, I added a new
CommandDest. This works well for the most part, with one exception: the
current DestFunction API doesn't provide enough information to allow the
Executor to store results into an arbitrary tuple store (where the
particular tuple store to use is chosen by the call site of
ExecutorRun). To workaround this, I've temporarily hacked up a solution
that works, but is not ideal: since the receiveTuple DestFunction is
passed the portal name, we can use that to lookup the Portal data
structure for the cursor and then use that to get at the tuple store the
Portal is using. This unnecessarily ties the Portal code with the
tupleReceiver code, but it works...
The proper fix for this is probably to change the DestFunction API --
Tom suggested passing the full QueryDesc to the receiveTuple function.
In that case, callers of ExecutorRun could "subclass" QueryDesc to add
any additional fields that their particular CommandDest needed to get
access to. This approach would work, but I'd like to think about it for
a little bit longer before deciding which route to go. In the mean time,
the code works fine, so I don't think a fix is urgent.
- (semi-related) I added a NO SCROLL keyword to DECLARE CURSOR, and
adjusted the behavior of SCROLL in accordance with the discussion on
-hackers.
- (unrelated) Cleaned up some SGML markup in sql.sgml, copy.sgml
Neil Conway
2003-03-27 17:51:29 +01:00
|
|
|
* Standard top-level contexts. For a description of the purpose of each
|
|
|
|
* of these contexts, refer to src/backend/utils/mmgr/README
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
MemoryContext TopMemoryContext = NULL;
|
|
|
|
MemoryContext ErrorContext = NULL;
|
|
|
|
MemoryContext PostmasterContext = NULL;
|
|
|
|
MemoryContext CacheMemoryContext = NULL;
|
2003-05-02 22:54:36 +02:00
|
|
|
MemoryContext MessageContext = NULL;
|
2000-06-28 05:33:33 +02:00
|
|
|
MemoryContext TopTransactionContext = NULL;
|
2004-07-01 02:52:04 +02:00
|
|
|
MemoryContext CurTransactionContext = NULL;
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/* This is a transient link to the active portal's memory context: */
|
2003-05-02 22:54:36 +02:00
|
|
|
MemoryContext PortalContext = NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2015-02-27 23:16:40 +01:00
|
|
|
static void MemoryContextCallResetCallbacks(MemoryContext context);
|
2015-08-25 19:09:48 +02:00
|
|
|
static void MemoryContextStatsInternal(MemoryContext context, int level,
|
2019-05-22 19:04:48 +02:00
|
|
|
bool print, int max_children,
|
|
|
|
MemoryContextCounters *totals);
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
|
2019-05-22 19:04:48 +02:00
|
|
|
const char *stats_string);
|
2007-08-07 08:25:14 +02:00
|
|
|
|
2014-04-04 13:27:18 +02:00
|
|
|
/*
|
|
|
|
* You should not do memory allocations within a critical section, because
|
|
|
|
* an out-of-memory error will be escalated to a PANIC. To enforce that
|
|
|
|
* rule, the allocation functions Assert that.
|
|
|
|
*/
|
|
|
|
#define AssertNotInCriticalSection(context) \
|
2014-06-30 09:13:48 +02:00
|
|
|
Assert(CritSectionCount == 0 || (context)->allowInCritSection)
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* EXPORTED ROUTINES *
|
|
|
|
*****************************************************************************/
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextInit
|
|
|
|
* Start up the memory-context subsystem.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-06-28 05:33:33 +02:00
|
|
|
* This must be called before creating contexts or allocating memory in
|
|
|
|
* contexts. TopMemoryContext and ErrorContext are initialized here;
|
|
|
|
* other contexts must be created afterwards.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-06-28 05:33:33 +02:00
|
|
|
* In normal multi-backend operation, this is called once during
|
|
|
|
* postmaster startup, and not at all by individual backend startup
|
|
|
|
* (since the backends inherit an already-initialized context subsystem
|
2014-01-11 22:35:26 +01:00
|
|
|
* by virtue of being forked off the postmaster). But in an EXEC_BACKEND
|
|
|
|
* build, each process must do this for itself.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-06-28 05:33:33 +02:00
|
|
|
* In a standalone backend this must be called during backend startup.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
2000-06-28 05:33:33 +02:00
|
|
|
MemoryContextInit(void)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-28 05:33:33 +02:00
|
|
|
AssertState(TopMemoryContext == NULL);
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
* First, initialize TopMemoryContext, which is the parent of all others.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
|
|
|
TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
|
|
|
|
"TopMemoryContext",
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
2016-08-27 23:50:38 +02:00
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Not having any other place to point CurrentMemoryContext, make it point
|
|
|
|
* to TopMemoryContext. Caller should change this soon!
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
|
|
|
CurrentMemoryContext = TopMemoryContext;
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Initialize ErrorContext as an AllocSetContext with slow growth rate ---
|
|
|
|
* we don't really expect much to be allocated in it. More to the point,
|
|
|
|
* require it to contain at least 8K at all times. This is the only case
|
|
|
|
* where retained memory in a context is *essential* --- we want to be
|
|
|
|
* sure ErrorContext still has some memory even if we've run out
|
2014-06-30 09:13:48 +02:00
|
|
|
* elsewhere! Also, allow allocations in ErrorContext within a critical
|
2015-02-27 23:16:40 +01:00
|
|
|
* section. Otherwise a PANIC will cause an assertion failure in the error
|
|
|
|
* reporting code, before printing out the real cause of the failure.
|
2014-01-11 22:35:26 +01:00
|
|
|
*
|
|
|
|
* This should be the last step in this function, as elog.c assumes memory
|
|
|
|
* management works once ErrorContext is non-null.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2018-10-12 20:26:56 +02:00
|
|
|
ErrorContext = AllocSetContextCreate(TopMemoryContext,
|
|
|
|
"ErrorContext",
|
|
|
|
8 * 1024,
|
|
|
|
8 * 1024,
|
|
|
|
8 * 1024);
|
2014-06-30 09:13:48 +02:00
|
|
|
MemoryContextAllowInCriticalSection(ErrorContext, true);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextReset
|
2015-02-28 00:09:42 +01:00
|
|
|
* Release all space allocated within a context and delete all its
|
|
|
|
* descendant contexts (but not the named context itself).
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void
|
|
|
|
MemoryContextReset(MemoryContext context)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-08-22 06:00:10 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
2005-05-15 01:16:29 +02:00
|
|
|
/* save a function call in common case where there are no children */
|
|
|
|
if (context->firstchild != NULL)
|
2015-02-28 00:09:42 +01:00
|
|
|
MemoryContextDeleteChildren(context);
|
|
|
|
|
|
|
|
/* save a function call if no pallocs since startup or last reset */
|
|
|
|
if (!context->isReset)
|
|
|
|
MemoryContextResetOnly(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MemoryContextResetOnly
|
|
|
|
* Release all space allocated within a context.
|
|
|
|
* Nothing is done to the context's descendant contexts.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MemoryContextResetOnly(MemoryContext context)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2005-05-15 01:16:29 +02:00
|
|
|
|
2011-05-21 20:47:19 +02:00
|
|
|
/* Nothing to do if no pallocs since startup or last reset */
|
|
|
|
if (!context->isReset)
|
|
|
|
{
|
2015-02-27 23:16:40 +01:00
|
|
|
MemoryContextCallResetCallbacks(context);
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If context->ident points into the context's memory, it will become
|
|
|
|
* a dangling pointer. We could prevent that by setting it to NULL
|
|
|
|
* here, but that would break valid coding patterns that keep the
|
|
|
|
* ident elsewhere, e.g. in a parent context. Another idea is to use
|
|
|
|
* MemoryContextContains(), but we don't require ident strings to be
|
|
|
|
* in separately-palloc'd chunks, so that risks false positives. So
|
|
|
|
* for now we assume the programmer got it right.
|
|
|
|
*/
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
context->methods->reset(context);
|
2011-05-21 20:47:19 +02:00
|
|
|
context->isReset = true;
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_DESTROY_MEMPOOL(context);
|
|
|
|
VALGRIND_CREATE_MEMPOOL(context, 0, false);
|
2011-05-21 20:47:19 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextResetChildren
|
|
|
|
* Release all space allocated within a context's descendants,
|
|
|
|
* but don't delete the contexts themselves. The named context
|
|
|
|
* itself is not touched.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
2000-06-28 05:33:33 +02:00
|
|
|
MemoryContextResetChildren(MemoryContext context)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
MemoryContext child;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-08-22 06:00:10 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
for (child = context->firstchild; child != NULL; child = child->nextchild)
|
2015-02-28 00:09:42 +01:00
|
|
|
{
|
|
|
|
MemoryContextResetChildren(child);
|
|
|
|
MemoryContextResetOnly(child);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextDelete
|
|
|
|
* Delete a context and its descendants, and release all space
|
|
|
|
* allocated therein.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
* The type-specific delete routine removes all storage for the context,
|
|
|
|
* but we have to recurse to handle the children.
|
|
|
|
* We must also delink the context from its parent, if it has one.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void
|
|
|
|
MemoryContextDelete(MemoryContext context)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-08-22 06:00:10 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2000-06-28 05:33:33 +02:00
|
|
|
/* We had better not be deleting TopMemoryContext ... */
|
|
|
|
Assert(context != TopMemoryContext);
|
|
|
|
/* And not CurrentMemoryContext, either */
|
|
|
|
Assert(context != CurrentMemoryContext);
|
|
|
|
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
/* save a function call in common case where there are no children */
|
|
|
|
if (context->firstchild != NULL)
|
|
|
|
MemoryContextDeleteChildren(context);
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2015-02-27 23:16:40 +01:00
|
|
|
/*
|
|
|
|
* It's not entirely clear whether 'tis better to do this before or after
|
|
|
|
* delinking the context; but an error in a callback will likely result in
|
|
|
|
* leaking the whole context (if it's not a root context) if we do it
|
|
|
|
* after, so let's do it before.
|
|
|
|
*/
|
|
|
|
MemoryContextCallResetCallbacks(context);
|
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* We delink the context from its parent before deleting it, so that if
|
|
|
|
* there's an error we won't have deleted/busted contexts still attached
|
|
|
|
* to the context tree. Better a leak than a crash.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2011-09-11 22:29:42 +02:00
|
|
|
MemoryContextSetParent(context, NULL);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
/*
|
|
|
|
* Also reset the context's ident pointer, in case it points into the
|
|
|
|
* context. This would only matter if someone tries to get stats on the
|
|
|
|
* (already unlinked) context, which is unlikely, but let's be safe.
|
|
|
|
*/
|
|
|
|
context->ident = NULL;
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
context->methods->delete_context(context);
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_DESTROY_MEMPOOL(context);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextDeleteChildren
|
|
|
|
* Delete all the descendants of the named context and release all
|
|
|
|
* space allocated therein. The named context itself is not touched.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void
|
|
|
|
MemoryContextDeleteChildren(MemoryContext context)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-08-22 06:00:10 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* MemoryContextDelete will delink the child from me, so just iterate as
|
|
|
|
* long as there is a child.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
|
|
|
while (context->firstchild != NULL)
|
|
|
|
MemoryContextDelete(context->firstchild);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2015-02-27 23:16:40 +01:00
|
|
|
/*
|
|
|
|
* MemoryContextRegisterResetCallback
|
|
|
|
* Register a function to be called before next context reset/delete.
|
|
|
|
* Such callbacks will be called in reverse order of registration.
|
|
|
|
*
|
|
|
|
* The caller is responsible for allocating a MemoryContextCallback struct
|
|
|
|
* to hold the info about this callback request, and for filling in the
|
|
|
|
* "func" and "arg" fields in the struct to show what function to call with
|
|
|
|
* what argument. Typically the callback struct should be allocated within
|
|
|
|
* the specified context, since that means it will automatically be freed
|
|
|
|
* when no longer needed.
|
|
|
|
*
|
|
|
|
* There is no API for deregistering a callback once registered. If you
|
|
|
|
* want it to not do anything anymore, adjust the state pointed to by its
|
|
|
|
* "arg" to indicate that.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MemoryContextRegisterResetCallback(MemoryContext context,
|
|
|
|
MemoryContextCallback *cb)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
|
|
|
/* Push onto head so this will be called before older registrants. */
|
|
|
|
cb->next = context->reset_cbs;
|
|
|
|
context->reset_cbs = cb;
|
|
|
|
/* Mark the context as non-reset (it probably is already). */
|
|
|
|
context->isReset = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MemoryContextCallResetCallbacks
|
|
|
|
* Internal function to call all registered callbacks for context.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
MemoryContextCallResetCallbacks(MemoryContext context)
|
|
|
|
{
|
|
|
|
MemoryContextCallback *cb;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We pop each callback from the list before calling. That way, if an
|
|
|
|
* error occurs inside the callback, we won't try to call it a second time
|
|
|
|
* in the likely event that we reset or delete the context later.
|
|
|
|
*/
|
|
|
|
while ((cb = context->reset_cbs) != NULL)
|
|
|
|
{
|
|
|
|
context->reset_cbs = cb->next;
|
2017-09-07 18:06:23 +02:00
|
|
|
cb->func(cb->arg);
|
2015-02-27 23:16:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextSetIdentifier
|
|
|
|
* Set the identifier string for a memory context.
|
|
|
|
*
|
|
|
|
* An identifier can be provided to help distinguish among different contexts
|
|
|
|
* of the same kind in memory context stats dumps. The identifier string
|
|
|
|
* must live at least as long as the context it is for; typically it is
|
|
|
|
* allocated inside that context, so that it automatically goes away on
|
|
|
|
* context deletion. Pass id = NULL to forget any old identifier.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MemoryContextSetIdentifier(MemoryContext context, const char *id)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
context->ident = id;
|
|
|
|
}
|
|
|
|
|
2011-09-11 22:29:42 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextSetParent
|
|
|
|
* Change a context to belong to a new parent (or no parent).
|
|
|
|
*
|
|
|
|
* We provide this as an API function because it is sometimes useful to
|
|
|
|
* change a context's lifespan after creation. For example, a context
|
|
|
|
* might be created underneath a transient context, filled with data,
|
|
|
|
* and then reparented underneath CacheMemoryContext to make it long-lived.
|
|
|
|
* In this way no special effort is needed to get rid of the context in case
|
|
|
|
* a failure occurs before its contents are completely set up.
|
|
|
|
*
|
|
|
|
* Callers often assume that this function cannot fail, so don't put any
|
|
|
|
* elog(ERROR) calls in it.
|
|
|
|
*
|
|
|
|
* A possible caller error is to reparent a context under itself, creating
|
|
|
|
* a loop in the context graph. We assert here that context != new_parent,
|
|
|
|
* but checking for multi-level loops seems more trouble than it's worth.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
AssertArg(context != new_parent);
|
|
|
|
|
Support "expanded" objects, particularly arrays, for better performance.
This patch introduces the ability for complex datatypes to have an
in-memory representation that is different from their on-disk format.
On-disk formats are typically optimized for minimal size, and in any case
they can't contain pointers, so they are often not well-suited for
computation. Now a datatype can invent an "expanded" in-memory format
that is better suited for its operations, and then pass that around among
the C functions that operate on the datatype. There are also provisions
(rudimentary as yet) to allow an expanded object to be modified in-place
under suitable conditions, so that operations like assignment to an element
of an array need not involve copying the entire array.
The initial application for this feature is arrays, but it is not hard
to foresee using it for other container types like JSON, XML and hstore.
I have hopes that it will be useful to PostGIS as well.
In this initial implementation, a few heuristics have been hard-wired
into plpgsql to improve performance for arrays that are stored in
plpgsql variables. We would like to generalize those hacks so that
other datatypes can obtain similar improvements, but figuring out some
appropriate APIs is left as a task for future work. (The heuristics
themselves are probably not optimal yet, either, as they sometimes
force expansion of arrays that would be better left alone.)
Preliminary performance testing shows impressive speed gains for plpgsql
functions that do element-by-element access or update of large arrays.
There are other cases that get a little slower, as a result of added array
format conversions; but we can hope to improve anything that's annoyingly
bad. In any case most applications should see a net win.
Tom Lane, reviewed by Andres Freund
2015-05-14 18:08:40 +02:00
|
|
|
/* Fast path if it's got correct parent already */
|
|
|
|
if (new_parent == context->parent)
|
|
|
|
return;
|
|
|
|
|
2011-09-11 22:29:42 +02:00
|
|
|
/* Delink from existing parent, if any */
|
|
|
|
if (context->parent)
|
|
|
|
{
|
|
|
|
MemoryContext parent = context->parent;
|
|
|
|
|
2015-12-09 00:32:49 +01:00
|
|
|
if (context->prevchild != NULL)
|
|
|
|
context->prevchild->nextchild = context->nextchild;
|
2011-09-11 22:29:42 +02:00
|
|
|
else
|
|
|
|
{
|
2015-12-09 00:32:49 +01:00
|
|
|
Assert(parent->firstchild == context);
|
|
|
|
parent->firstchild = context->nextchild;
|
2011-09-11 22:29:42 +02:00
|
|
|
}
|
2015-12-09 00:32:49 +01:00
|
|
|
|
|
|
|
if (context->nextchild != NULL)
|
|
|
|
context->nextchild->prevchild = context->prevchild;
|
2011-09-11 22:29:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* And relink */
|
|
|
|
if (new_parent)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(new_parent));
|
|
|
|
context->parent = new_parent;
|
2015-12-09 00:32:49 +01:00
|
|
|
context->prevchild = NULL;
|
2011-09-11 22:29:42 +02:00
|
|
|
context->nextchild = new_parent->firstchild;
|
2015-12-09 00:32:49 +01:00
|
|
|
if (new_parent->firstchild != NULL)
|
|
|
|
new_parent->firstchild->prevchild = context;
|
2011-09-11 22:29:42 +02:00
|
|
|
new_parent->firstchild = context;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
context->parent = NULL;
|
2015-12-09 00:32:49 +01:00
|
|
|
context->prevchild = NULL;
|
2011-09-11 22:29:42 +02:00
|
|
|
context->nextchild = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-30 09:13:48 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextAllowInCriticalSection
|
|
|
|
* Allow/disallow allocations in this memory context within a critical
|
|
|
|
* section.
|
|
|
|
*
|
|
|
|
* Normally, memory allocations are not allowed within a critical section,
|
|
|
|
* because a failure would lead to PANIC. There are a few exceptions to
|
|
|
|
* that, like allocations related to debugging code that is not supposed to
|
|
|
|
* be enabled in production. This function can be used to exempt specific
|
|
|
|
* memory contexts from the assertion in palloc().
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2015-02-27 23:16:40 +01:00
|
|
|
|
2014-06-30 09:13:48 +02:00
|
|
|
context->allowInCritSection = allow;
|
|
|
|
}
|
|
|
|
|
2002-08-12 02:36:12 +02:00
|
|
|
/*
|
|
|
|
* GetMemoryChunkSpace
|
|
|
|
* Given a currently-allocated chunk, determine the total space
|
|
|
|
* it occupies (including all memory-allocation overhead).
|
|
|
|
*
|
|
|
|
* This is useful for measuring the total space occupied by a set of
|
|
|
|
* allocated chunks.
|
|
|
|
*/
|
|
|
|
Size
|
|
|
|
GetMemoryChunkSpace(void *pointer)
|
|
|
|
{
|
2017-02-28 08:32:22 +01:00
|
|
|
MemoryContext context = GetMemoryChunkContext(pointer);
|
2002-08-12 02:36:12 +02:00
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
return context->methods->get_chunk_space(context, pointer);
|
2002-12-16 17:22:46 +01:00
|
|
|
}
|
|
|
|
|
2011-09-16 06:42:53 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextGetParent
|
|
|
|
* Get the parent context (if any) of the specified context
|
|
|
|
*/
|
|
|
|
MemoryContext
|
|
|
|
MemoryContextGetParent(MemoryContext context)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
|
|
|
return context->parent;
|
|
|
|
}
|
|
|
|
|
2004-09-16 22:17:49 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextIsEmpty
|
|
|
|
* Is a memory context empty of any allocated space?
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
MemoryContextIsEmpty(MemoryContext context)
|
|
|
|
{
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For now, we consider a memory context nonempty if it has any children;
|
|
|
|
* perhaps this should be changed later.
|
|
|
|
*/
|
|
|
|
if (context->firstchild != NULL)
|
|
|
|
return false;
|
|
|
|
/* Otherwise use the type-specific inquiry */
|
2017-09-07 18:06:23 +02:00
|
|
|
return context->methods->is_empty(context);
|
2004-09-16 22:17:49 +02:00
|
|
|
}
|
|
|
|
|
2019-10-01 03:13:39 +02:00
|
|
|
/*
|
|
|
|
* Find the memory allocated to blocks for this memory context. If recurse is
|
|
|
|
* true, also include children.
|
|
|
|
*/
|
|
|
|
int64
|
|
|
|
MemoryContextMemAllocated(MemoryContext context, bool recurse)
|
|
|
|
{
|
|
|
|
int64 total = context->mem_allocated;
|
|
|
|
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
|
|
|
if (recurse)
|
|
|
|
{
|
|
|
|
MemoryContext child = context->firstchild;
|
|
|
|
|
|
|
|
for (child = context->firstchild;
|
|
|
|
child != NULL;
|
|
|
|
child = child->nextchild)
|
|
|
|
total += MemoryContextMemAllocated(child, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextStats
|
|
|
|
* Print statistics about the named context and all its descendants.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2015-08-25 19:09:48 +02:00
|
|
|
* This is just a debugging utility, so it's not very fancy. However, we do
|
|
|
|
* make some effort to summarize when the output would otherwise be very long.
|
|
|
|
* The statistics are sent to stderr.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void
|
|
|
|
MemoryContextStats(MemoryContext context)
|
2007-08-07 08:25:14 +02:00
|
|
|
{
|
2015-08-25 19:09:48 +02:00
|
|
|
/* A hard-wired limit on the number of children is usually good enough */
|
|
|
|
MemoryContextStatsDetail(context, 100);
|
2007-08-07 08:25:14 +02:00
|
|
|
}
|
|
|
|
|
2015-08-25 19:09:48 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextStatsDetail
|
|
|
|
*
|
|
|
|
* Entry point for use if you want to vary the number of child contexts shown.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
MemoryContextStatsDetail(MemoryContext context, int max_children)
|
|
|
|
{
|
|
|
|
MemoryContextCounters grand_totals;
|
|
|
|
|
|
|
|
memset(&grand_totals, 0, sizeof(grand_totals));
|
|
|
|
|
|
|
|
MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals);
|
|
|
|
|
|
|
|
fprintf(stderr,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
"Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n",
|
2015-08-25 19:09:48 +02:00
|
|
|
grand_totals.totalspace, grand_totals.nblocks,
|
|
|
|
grand_totals.freespace, grand_totals.freechunks,
|
|
|
|
grand_totals.totalspace - grand_totals.freespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MemoryContextStatsInternal
|
|
|
|
* One recursion level for MemoryContextStats
|
|
|
|
*
|
|
|
|
* Print this context if print is true, but in any case accumulate counts into
|
|
|
|
* *totals (if given).
|
|
|
|
*/
|
2007-08-07 08:25:14 +02:00
|
|
|
static void
|
2015-08-25 19:09:48 +02:00
|
|
|
MemoryContextStatsInternal(MemoryContext context, int level,
|
|
|
|
bool print, int max_children,
|
|
|
|
MemoryContextCounters *totals)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2015-08-25 19:09:48 +02:00
|
|
|
MemoryContextCounters local_totals;
|
2001-03-22 05:01:46 +01:00
|
|
|
MemoryContext child;
|
2015-08-25 19:09:48 +02:00
|
|
|
int ichild;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-08-22 06:00:10 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
2015-08-25 19:09:48 +02:00
|
|
|
/* Examine the context itself */
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
context->methods->stats(context,
|
|
|
|
print ? MemoryContextStatsPrint : NULL,
|
|
|
|
(void *) &level,
|
|
|
|
totals);
|
2015-08-25 19:09:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Examine children. If there are more than max_children of them, we do
|
|
|
|
* not print the rest explicitly, but just summarize them.
|
|
|
|
*/
|
|
|
|
memset(&local_totals, 0, sizeof(local_totals));
|
|
|
|
|
|
|
|
for (child = context->firstchild, ichild = 0;
|
|
|
|
child != NULL;
|
|
|
|
child = child->nextchild, ichild++)
|
|
|
|
{
|
|
|
|
if (ichild < max_children)
|
|
|
|
MemoryContextStatsInternal(child, level + 1,
|
|
|
|
print, max_children,
|
|
|
|
totals);
|
|
|
|
else
|
|
|
|
MemoryContextStatsInternal(child, level + 1,
|
|
|
|
false, max_children,
|
|
|
|
&local_totals);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Deal with excess children */
|
|
|
|
if (ichild > max_children)
|
|
|
|
{
|
|
|
|
if (print)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i <= level; i++)
|
|
|
|
fprintf(stderr, " ");
|
|
|
|
fprintf(stderr,
|
|
|
|
"%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
|
|
|
|
ichild - max_children,
|
|
|
|
local_totals.totalspace,
|
|
|
|
local_totals.nblocks,
|
|
|
|
local_totals.freespace,
|
|
|
|
local_totals.freechunks,
|
|
|
|
local_totals.totalspace - local_totals.freespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (totals)
|
|
|
|
{
|
|
|
|
totals->nblocks += local_totals.nblocks;
|
|
|
|
totals->freechunks += local_totals.freechunks;
|
|
|
|
totals->totalspace += local_totals.totalspace;
|
|
|
|
totals->freespace += local_totals.freespace;
|
|
|
|
}
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextStatsPrint
|
|
|
|
* Print callback used by MemoryContextStatsInternal
|
|
|
|
*
|
|
|
|
* For now, the passthru pointer just points to "int level"; later we might
|
|
|
|
* make that more complicated.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
MemoryContextStatsPrint(MemoryContext context, void *passthru,
|
|
|
|
const char *stats_string)
|
|
|
|
{
|
|
|
|
int level = *(int *) passthru;
|
|
|
|
const char *name = context->name;
|
|
|
|
const char *ident = context->ident;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* It seems preferable to label dynahash contexts with just the hash table
|
|
|
|
* name. Those are already unique enough, so the "dynahash" part isn't
|
|
|
|
* very helpful, and this way is more consistent with pre-v11 practice.
|
|
|
|
*/
|
|
|
|
if (ident && strcmp(name, "dynahash") == 0)
|
|
|
|
{
|
|
|
|
name = ident;
|
|
|
|
ident = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < level; i++)
|
|
|
|
fprintf(stderr, " ");
|
|
|
|
fprintf(stderr, "%s: %s", name, stats_string);
|
|
|
|
if (ident)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Some contexts may have very long identifiers (e.g., SQL queries).
|
|
|
|
* Arbitrarily truncate at 100 bytes, but be careful not to break
|
|
|
|
* multibyte characters. Also, replace ASCII control characters, such
|
|
|
|
* as newlines, with spaces.
|
|
|
|
*/
|
|
|
|
int idlen = strlen(ident);
|
|
|
|
bool truncated = false;
|
|
|
|
|
|
|
|
if (idlen > 100)
|
|
|
|
{
|
|
|
|
idlen = pg_mbcliplen(ident, idlen, 100);
|
|
|
|
truncated = true;
|
|
|
|
}
|
|
|
|
fprintf(stderr, ": ");
|
|
|
|
while (idlen-- > 0)
|
|
|
|
{
|
|
|
|
unsigned char c = *ident++;
|
|
|
|
|
|
|
|
if (c < ' ')
|
|
|
|
c = ' ';
|
|
|
|
fputc(c, stderr);
|
|
|
|
}
|
|
|
|
if (truncated)
|
|
|
|
fprintf(stderr, "...");
|
|
|
|
}
|
|
|
|
fputc('\n', stderr);
|
|
|
|
}
|
|
|
|
|
Here is the patch with memory leak checker. This checker allow detect
in-chunk leaks, overwrite-next-chunk leaks and overwrite block-freeptr leaks.
A in-chunk leak --- if something overwrite space after wanted (via palloc()
size, but it is still inside chunk. For example
x = palloc(12); /* create 16b chunk */
memset(x, '#', 13);
this leak is in the current source total invisible, because chunk is 16b and
leak is in the "align space".
For this feature I add data_size to StandardChunk, and all memory which go
from AllocSetAlloc() is marked as 0x7F.
The MemoryContextCheck() is compiled '#ifdef USE_ASSERT_CHECKING'.
I add this checking to 'tcop/postgres.c' and is active after each backend
query, but it is probably not sufficient, because some MemoryContext exist
only during memory processing --- will good if someone who known where
it is needful (Tom:-) add it for others contexts;
A problem in the current source is that we have still some malloc()
allocation that is not needful and this allocation is total invisible for
all context routines. For example Dllist in backend (pretty dirty it is in
catcache where values in Dllist are palloc-ed, but list is malloc-ed).
--- and BTW. this Dllist design stand in the way for query cache :-)
Tom, if you agree I start replace some mallocs.
BTW. --- Tom, have you idea for across transaction presistent allocation for
SQL functions? (like regex - now it is via malloc)
I almost forget. I add one if() to AllocSetAlloc(), for 'size' that are
greater than ALLOC_BIGCHUNK_LIMIT is not needful check AllocSetFreeIndex(),
because 'fidx' is always 'ALLOCSET_NUM_FREELISTS - 1'. It a little brisk up
allocation for very large chunks. Right?
Karel
2000-07-11 16:30:37 +02:00
|
|
|
/*
|
|
|
|
* MemoryContextCheck
|
|
|
|
* Check all chunks in the named context.
|
|
|
|
*
|
2001-03-22 05:01:46 +01:00
|
|
|
* This is just a debugging utility, so it's not fancy.
|
Here is the patch with memory leak checker. This checker allow detect
in-chunk leaks, overwrite-next-chunk leaks and overwrite block-freeptr leaks.
A in-chunk leak --- if something overwrite space after wanted (via palloc()
size, but it is still inside chunk. For example
x = palloc(12); /* create 16b chunk */
memset(x, '#', 13);
this leak is in the current source total invisible, because chunk is 16b and
leak is in the "align space".
For this feature I add data_size to StandardChunk, and all memory which go
from AllocSetAlloc() is marked as 0x7F.
The MemoryContextCheck() is compiled '#ifdef USE_ASSERT_CHECKING'.
I add this checking to 'tcop/postgres.c' and is active after each backend
query, but it is probably not sufficient, because some MemoryContext exist
only during memory processing --- will good if someone who known where
it is needful (Tom:-) add it for others contexts;
A problem in the current source is that we have still some malloc()
allocation that is not needful and this allocation is total invisible for
all context routines. For example Dllist in backend (pretty dirty it is in
catcache where values in Dllist are palloc-ed, but list is malloc-ed).
--- and BTW. this Dllist design stand in the way for query cache :-)
Tom, if you agree I start replace some mallocs.
BTW. --- Tom, have you idea for across transaction presistent allocation for
SQL functions? (like regex - now it is via malloc)
I almost forget. I add one if() to AllocSetAlloc(), for 'size' that are
greater than ALLOC_BIGCHUNK_LIMIT is not needful check AllocSetFreeIndex(),
because 'fidx' is always 'ALLOCSET_NUM_FREELISTS - 1'. It a little brisk up
allocation for very large chunks. Right?
Karel
2000-07-11 16:30:37 +02:00
|
|
|
*/
|
|
|
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
|
|
void
|
|
|
|
MemoryContextCheck(MemoryContext context)
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
MemoryContext child;
|
Here is the patch with memory leak checker. This checker allow detect
in-chunk leaks, overwrite-next-chunk leaks and overwrite block-freeptr leaks.
A in-chunk leak --- if something overwrite space after wanted (via palloc()
size, but it is still inside chunk. For example
x = palloc(12); /* create 16b chunk */
memset(x, '#', 13);
this leak is in the current source total invisible, because chunk is 16b and
leak is in the "align space".
For this feature I add data_size to StandardChunk, and all memory which go
from AllocSetAlloc() is marked as 0x7F.
The MemoryContextCheck() is compiled '#ifdef USE_ASSERT_CHECKING'.
I add this checking to 'tcop/postgres.c' and is active after each backend
query, but it is probably not sufficient, because some MemoryContext exist
only during memory processing --- will good if someone who known where
it is needful (Tom:-) add it for others contexts;
A problem in the current source is that we have still some malloc()
allocation that is not needful and this allocation is total invisible for
all context routines. For example Dllist in backend (pretty dirty it is in
catcache where values in Dllist are palloc-ed, but list is malloc-ed).
--- and BTW. this Dllist design stand in the way for query cache :-)
Tom, if you agree I start replace some mallocs.
BTW. --- Tom, have you idea for across transaction presistent allocation for
SQL functions? (like regex - now it is via malloc)
I almost forget. I add one if() to AllocSetAlloc(), for 'size' that are
greater than ALLOC_BIGCHUNK_LIMIT is not needful check AllocSetFreeIndex(),
because 'fidx' is always 'ALLOCSET_NUM_FREELISTS - 1'. It a little brisk up
allocation for very large chunks. Right?
Karel
2000-07-11 16:30:37 +02:00
|
|
|
|
2000-08-22 06:00:10 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
context->methods->check(context);
|
Here is the patch with memory leak checker. This checker allow detect
in-chunk leaks, overwrite-next-chunk leaks and overwrite block-freeptr leaks.
A in-chunk leak --- if something overwrite space after wanted (via palloc()
size, but it is still inside chunk. For example
x = palloc(12); /* create 16b chunk */
memset(x, '#', 13);
this leak is in the current source total invisible, because chunk is 16b and
leak is in the "align space".
For this feature I add data_size to StandardChunk, and all memory which go
from AllocSetAlloc() is marked as 0x7F.
The MemoryContextCheck() is compiled '#ifdef USE_ASSERT_CHECKING'.
I add this checking to 'tcop/postgres.c' and is active after each backend
query, but it is probably not sufficient, because some MemoryContext exist
only during memory processing --- will good if someone who known where
it is needful (Tom:-) add it for others contexts;
A problem in the current source is that we have still some malloc()
allocation that is not needful and this allocation is total invisible for
all context routines. For example Dllist in backend (pretty dirty it is in
catcache where values in Dllist are palloc-ed, but list is malloc-ed).
--- and BTW. this Dllist design stand in the way for query cache :-)
Tom, if you agree I start replace some mallocs.
BTW. --- Tom, have you idea for across transaction presistent allocation for
SQL functions? (like regex - now it is via malloc)
I almost forget. I add one if() to AllocSetAlloc(), for 'size' that are
greater than ALLOC_BIGCHUNK_LIMIT is not needful check AllocSetFreeIndex(),
because 'fidx' is always 'ALLOCSET_NUM_FREELISTS - 1'. It a little brisk up
allocation for very large chunks. Right?
Karel
2000-07-11 16:30:37 +02:00
|
|
|
for (child = context->firstchild; child != NULL; child = child->nextchild)
|
|
|
|
MemoryContextCheck(child);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextContains
|
|
|
|
* Detect whether an allocated chunk of memory belongs to a given
|
|
|
|
* context or not.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-06-28 05:33:33 +02:00
|
|
|
* Caution: this test is reliable as long as 'pointer' does point to
|
|
|
|
* a chunk of memory allocated from *some* context. If 'pointer' points
|
|
|
|
* at memory obtained in some other way, there is a small chance of a
|
|
|
|
* false-positive result, since the bits right before it might look like
|
|
|
|
* a valid chunk header by chance.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
bool
|
|
|
|
MemoryContextContains(MemoryContext context, void *pointer)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2017-03-01 05:41:44 +01:00
|
|
|
MemoryContext ptr_context;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NB: Can't use GetMemoryChunkContext() here - that performs assertions
|
|
|
|
* that aren't acceptable here since we might be passed memory not
|
|
|
|
* allocated by any memory context.
|
|
|
|
*
|
|
|
|
* Try to detect bogus pointers handed to us, poorly though we can.
|
|
|
|
* Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
|
|
|
|
* allocated chunk.
|
|
|
|
*/
|
|
|
|
if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, it's probably safe to look at the context.
|
|
|
|
*/
|
|
|
|
ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2017-02-28 08:32:22 +01:00
|
|
|
return ptr_context == context;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextCreate
|
|
|
|
* Context-type-independent part of context creation.
|
|
|
|
*
|
|
|
|
* This is only intended to be called by context-type-specific
|
|
|
|
* context creation routines, not by the unwashed masses.
|
|
|
|
*
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
* The memory context creation procedure goes like this:
|
|
|
|
* 1. Context-type-specific routine makes some initial space allocation,
|
|
|
|
* including enough space for the context header. If it fails,
|
|
|
|
* it can ereport() with no damage done.
|
|
|
|
* 2. Context-type-specific routine sets up all type-specific fields of
|
|
|
|
* the header (those beyond MemoryContextData proper), as well as any
|
|
|
|
* other management fields it needs to have a fully valid context.
|
|
|
|
* Usually, failure in this step is impossible, but if it's possible
|
|
|
|
* the initial space allocation should be freed before ereport'ing.
|
|
|
|
* 3. Context-type-specific routine calls MemoryContextCreate() to fill in
|
|
|
|
* the generic header fields and link the context into the context tree.
|
|
|
|
* 4. We return to the context-type-specific routine, which finishes
|
2000-06-28 05:33:33 +02:00
|
|
|
* up type-specific initialization. This routine can now do things
|
|
|
|
* that might fail (like allocate more memory), so long as it's
|
|
|
|
* sure the node is left in a state that delete will handle.
|
|
|
|
*
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
* node: the as-yet-uninitialized common part of the context header node.
|
|
|
|
* tag: NodeTag code identifying the memory context type.
|
|
|
|
* methods: context-type-specific methods (usually statically allocated).
|
|
|
|
* parent: parent context, or NULL if this will be a top-level context.
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
* name: name of context (must be statically allocated).
|
2000-06-28 05:33:33 +02:00
|
|
|
*
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
* Context routines generally assume that MemoryContextCreate can't fail,
|
|
|
|
* so this can contain Assert but not elog/ereport.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
void
|
|
|
|
MemoryContextCreate(MemoryContext node,
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
NodeTag tag,
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
const MemoryContextMethods *methods,
|
2000-06-28 05:33:33 +02:00
|
|
|
MemoryContext parent,
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
const char *name)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
/* Creating new memory contexts is not allowed in a critical section */
|
2014-04-04 13:27:18 +02:00
|
|
|
Assert(CritSectionCount == 0);
|
|
|
|
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
/* Initialize all standard fields of memory context header */
|
2000-06-28 05:33:33 +02:00
|
|
|
node->type = tag;
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
node->isReset = true;
|
2000-06-28 05:33:33 +02:00
|
|
|
node->methods = methods;
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
node->parent = parent;
|
2000-06-28 05:33:33 +02:00
|
|
|
node->firstchild = NULL;
|
2019-10-01 03:13:39 +02:00
|
|
|
node->mem_allocated = 0;
|
2015-12-09 00:32:49 +01:00
|
|
|
node->prevchild = NULL;
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
node->name = name;
|
|
|
|
node->ident = NULL;
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
node->reset_cbs = NULL;
|
2000-06-28 05:33:33 +02:00
|
|
|
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
/* OK to link node into context tree */
|
2000-06-28 05:33:33 +02:00
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
node->nextchild = parent->firstchild;
|
2015-12-09 00:32:49 +01:00
|
|
|
if (parent->firstchild != NULL)
|
|
|
|
parent->firstchild->prevchild = node;
|
2000-06-28 05:33:33 +02:00
|
|
|
parent->firstchild = node;
|
2014-06-30 09:13:48 +02:00
|
|
|
/* inherit allowInCritSection flag from parent */
|
|
|
|
node->allowInCritSection = parent->allowInCritSection;
|
2000-06-28 05:33:33 +02:00
|
|
|
}
|
Rethink MemoryContext creation to improve performance.
This patch makes a number of interrelated changes to reduce the overhead
involved in creating/deleting memory contexts. The key ideas are:
* Include the AllocSetContext header of an aset.c context in its first
malloc request, rather than allocating it separately in TopMemoryContext.
This means that we now always create an initial or "keeper" block in an
aset, even if it never receives any allocation requests.
* Create freelists in which we can save and recycle recently-destroyed
asets (this idea is due to Robert Haas).
* In the common case where the name of a context is a constant string,
just store a pointer to it in the context header, rather than copying
the string.
The first change eliminates a palloc/pfree cycle per context, and
also avoids bloat in TopMemoryContext, at the price that creating
a context now involves a malloc/free cycle even if the context never
receives any allocations. That would be a loser for some common
usage patterns, but recycling short-lived contexts via the freelist
eliminates that pain.
Avoiding copying constant strings not only saves strlen() and strcpy()
overhead, but is an essential part of the freelist optimization because
it makes the context header size constant. Currently we make no
attempt to use the freelist for contexts with non-constant names.
(Perhaps someday we'll need to think harder about that, but in current
usage, most contexts with custom names are long-lived anyway.)
The freelist management in this initial commit is pretty simplistic,
and we might want to refine it later --- but in common workloads that
will never matter because the freelists will never get full anyway.
To create a context with a non-constant name, one is now required to
call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
option. AllocSetContextCreate becomes a wrapper macro, and it includes
a test that will complain about non-string-literal context name
parameters on gcc and similar compilers.
An unfortunate side effect of making AllocSetContextCreate a macro is
that one is now *required* to use the size parameter abstraction macros
(ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
writing out individual size parameters no longer works unless you
switch to AllocSetContextCreateExtended.
Internally to the memory-context-related modules, the context creation
APIs are simplified, removing the rather baroque original design whereby
a context-type module called mcxt.c which then called back into the
context-type module. That saved a bit of code duplication, but not much,
and it prevented context-type modules from exercising control over the
allocation of context headers.
In passing, I converted the test-and-elog validation of aset size
parameters into Asserts to save a few more cycles. The original thought
was that callers might compute size parameters on the fly, but in practice
nobody does that, so it's useless to expend cycles on checking those
numbers in production builds.
Also, mark the memory context method-pointer structs "const",
just for cleanliness.
Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
2017-12-13 19:55:12 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
node->nextchild = NULL;
|
|
|
|
node->allowInCritSection = false;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_CREATE_MEMPOOL(node, 0, false);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextAlloc
|
|
|
|
* Allocate space within the specified context.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-06-28 05:33:33 +02:00
|
|
|
* This could be turned into a macro, but we'd have to import
|
|
|
|
* nodes/memnodes.h into postgres.h which seems a bad idea.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void *
|
|
|
|
MemoryContextAlloc(MemoryContext context, Size size)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2013-06-27 01:56:03 +02:00
|
|
|
void *ret;
|
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2014-04-04 13:27:18 +02:00
|
|
|
AssertNotInCriticalSection(context);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2001-02-06 02:53:53 +01:00
|
|
|
if (!AllocSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2011-05-21 20:47:19 +02:00
|
|
|
context->isReset = false;
|
2011-05-24 23:56:52 +02:00
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2015-01-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Here, and elsewhere in this module, we show the target context's
|
|
|
|
* "name" but not its "ident" (if any) in user-visible error messages.
|
|
|
|
* The "ident" string might contain security-sensitive data, such as
|
|
|
|
* values in SQL commands.
|
|
|
|
*/
|
2015-01-29 16:23:38 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-29 16:23:38 +01:00
|
|
|
}
|
|
|
|
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
2013-06-27 01:56:03 +02:00
|
|
|
|
|
|
|
return ret;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2002-11-10 03:17:25 +01:00
|
|
|
/*
|
2002-12-16 17:22:46 +01:00
|
|
|
* MemoryContextAllocZero
|
2002-11-10 03:17:25 +01:00
|
|
|
* Like MemoryContextAlloc, but clears allocated memory
|
|
|
|
*
|
|
|
|
* We could just call MemoryContextAlloc then clear the memory, but this
|
2002-12-16 17:22:46 +01:00
|
|
|
* is a very common combination, so we provide the combined operation.
|
2002-11-10 03:17:25 +01:00
|
|
|
*/
|
|
|
|
void *
|
2002-12-16 17:22:46 +01:00
|
|
|
MemoryContextAllocZero(MemoryContext context, Size size)
|
2002-11-10 03:17:25 +01:00
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
void *ret;
|
2002-11-10 03:17:25 +01:00
|
|
|
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2014-04-04 13:27:18 +02:00
|
|
|
AssertNotInCriticalSection(context);
|
2002-11-10 03:17:25 +01:00
|
|
|
|
|
|
|
if (!AllocSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
2002-11-10 03:17:25 +01:00
|
|
|
|
2011-05-24 23:56:52 +02:00
|
|
|
context->isReset = false;
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2015-01-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-29 16:23:38 +01:00
|
|
|
}
|
|
|
|
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
2002-12-16 17:22:46 +01:00
|
|
|
|
|
|
|
MemSetAligned(ret, 0, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MemoryContextAllocZeroAligned
|
|
|
|
* MemoryContextAllocZero where length is suitable for MemSetLoop
|
|
|
|
*
|
|
|
|
* This might seem overly specialized, but it's not because newNode()
|
|
|
|
* is so often called with compile-time-constant sizes.
|
|
|
|
*/
|
|
|
|
void *
|
|
|
|
MemoryContextAllocZeroAligned(MemoryContext context, Size size)
|
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
void *ret;
|
2002-12-16 17:22:46 +01:00
|
|
|
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2014-04-04 13:27:18 +02:00
|
|
|
AssertNotInCriticalSection(context);
|
2002-12-16 17:22:46 +01:00
|
|
|
|
|
|
|
if (!AllocSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
2002-12-16 17:22:46 +01:00
|
|
|
|
2011-05-24 23:56:52 +02:00
|
|
|
context->isReset = false;
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2015-01-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-29 16:23:38 +01:00
|
|
|
}
|
|
|
|
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
2002-12-16 17:22:46 +01:00
|
|
|
|
2002-11-13 01:37:06 +01:00
|
|
|
MemSetLoop(ret, 0, size);
|
2002-12-16 17:22:46 +01:00
|
|
|
|
2002-11-10 03:17:25 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-01-30 18:56:48 +01:00
|
|
|
/*
|
|
|
|
* MemoryContextAllocExtended
|
|
|
|
* Allocate space within the specified context using the given flags.
|
|
|
|
*/
|
|
|
|
void *
|
|
|
|
MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
|
|
|
|
{
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
AssertNotInCriticalSection(context);
|
|
|
|
|
|
|
|
if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
|
|
|
|
((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
|
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
|
|
|
|
|
|
|
context->isReset = false;
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2015-01-30 18:56:48 +01:00
|
|
|
{
|
|
|
|
if ((flags & MCXT_ALLOC_NO_OOM) == 0)
|
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-30 18:56:48 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
|
|
|
|
|
|
|
if ((flags & MCXT_ALLOC_ZERO) != 0)
|
|
|
|
MemSetAligned(ret, 0, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
void *
|
|
|
|
palloc(Size size)
|
|
|
|
{
|
|
|
|
/* duplicates MemoryContextAlloc to avoid increased overhead */
|
2013-06-27 01:56:03 +02:00
|
|
|
void *ret;
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
MemoryContext context = CurrentMemoryContext;
|
2013-06-27 01:56:03 +02:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
AssertNotInCriticalSection(context);
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
|
|
|
if (!AllocSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
context->isReset = false;
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
|
|
|
if (unlikely(ret == NULL))
|
2015-01-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-29 16:23:38 +01:00
|
|
|
}
|
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
2013-06-27 01:56:03 +02:00
|
|
|
|
|
|
|
return ret;
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
palloc0(Size size)
|
|
|
|
{
|
|
|
|
/* duplicates MemoryContextAllocZero to avoid increased overhead */
|
|
|
|
void *ret;
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
MemoryContext context = CurrentMemoryContext;
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
AssertNotInCriticalSection(context);
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
|
|
|
if (!AllocSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
context->isReset = false;
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
|
|
|
if (unlikely(ret == NULL))
|
2015-01-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-29 16:23:38 +01:00
|
|
|
}
|
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
|
|
|
|
MemSetAligned(ret, 0, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-03 10:36:12 +02:00
|
|
|
void *
|
|
|
|
palloc_extended(Size size, int flags)
|
|
|
|
{
|
|
|
|
/* duplicates MemoryContextAllocExtended to avoid increased overhead */
|
|
|
|
void *ret;
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
MemoryContext context = CurrentMemoryContext;
|
2015-04-03 10:36:12 +02:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
AssertArg(MemoryContextIsValid(context));
|
|
|
|
AssertNotInCriticalSection(context);
|
2015-04-03 10:36:12 +02:00
|
|
|
|
|
|
|
if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
|
|
|
|
((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
|
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
context->isReset = false;
|
2015-04-03 10:36:12 +02:00
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
|
|
|
if (unlikely(ret == NULL))
|
2015-04-03 10:36:12 +02:00
|
|
|
{
|
|
|
|
if ((flags & MCXT_ALLOC_NO_OOM) == 0)
|
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-04-03 10:36:12 +02:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
2015-04-03 10:36:12 +02:00
|
|
|
|
|
|
|
if ((flags & MCXT_ALLOC_ZERO) != 0)
|
|
|
|
MemSetAligned(ret, 0, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* pfree
|
|
|
|
* Release an allocated chunk.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void
|
|
|
|
pfree(void *pointer)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2017-02-28 08:32:22 +01:00
|
|
|
MemoryContext context = GetMemoryChunkContext(pointer);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
context->methods->free_p(context, pointer);
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_MEMPOOL_FREE(context, pointer);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* repalloc
|
2004-06-05 21:48:09 +02:00
|
|
|
* Adjust the size of a previously allocated chunk.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
void *
|
|
|
|
repalloc(void *pointer, Size size)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2017-02-28 08:32:22 +01:00
|
|
|
MemoryContext context = GetMemoryChunkContext(pointer);
|
2013-06-27 01:56:03 +02:00
|
|
|
void *ret;
|
|
|
|
|
|
|
|
if (!AllocSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2014-04-04 13:27:18 +02:00
|
|
|
AssertNotInCriticalSection(context);
|
2013-06-27 20:53:57 +02:00
|
|
|
|
|
|
|
/* isReset must be false already */
|
|
|
|
Assert(!context->isReset);
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->realloc(context, pointer, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2016-03-13 06:21:07 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
2015-01-29 16:23:38 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2016-03-13 06:21:07 +01:00
|
|
|
}
|
2015-01-29 16:23:38 +01:00
|
|
|
|
2013-06-27 20:53:57 +02:00
|
|
|
VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MemoryContextAllocHuge
|
|
|
|
* Allocate (possibly-expansive) space within the specified context.
|
|
|
|
*
|
|
|
|
* See considerations in comment at MaxAllocHugeSize.
|
|
|
|
*/
|
|
|
|
void *
|
|
|
|
MemoryContextAllocHuge(MemoryContext context, Size size)
|
|
|
|
{
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
AssertArg(MemoryContextIsValid(context));
|
2014-04-04 13:27:18 +02:00
|
|
|
AssertNotInCriticalSection(context);
|
2013-06-27 20:53:57 +02:00
|
|
|
|
|
|
|
if (!AllocHugeSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
2013-06-27 20:53:57 +02:00
|
|
|
|
|
|
|
context->isReset = false;
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->alloc(context, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2015-01-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2015-01-29 16:23:38 +01:00
|
|
|
}
|
|
|
|
|
2013-06-27 20:53:57 +02:00
|
|
|
VALGRIND_MEMPOOL_ALLOC(context, ret, size);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* repalloc_huge
|
|
|
|
* Adjust the size of a previously allocated chunk, permitting a large
|
|
|
|
* value. The previous allocation need not have been "huge".
|
|
|
|
*/
|
|
|
|
void *
|
|
|
|
repalloc_huge(void *pointer, Size size)
|
|
|
|
{
|
2017-02-28 08:32:22 +01:00
|
|
|
MemoryContext context = GetMemoryChunkContext(pointer);
|
2013-06-27 20:53:57 +02:00
|
|
|
void *ret;
|
|
|
|
|
|
|
|
if (!AllocHugeSizeIsValid(size))
|
2014-01-23 23:18:23 +01:00
|
|
|
elog(ERROR, "invalid memory alloc request size %zu", size);
|
2013-06-27 20:53:57 +02:00
|
|
|
|
2014-04-04 13:27:18 +02:00
|
|
|
AssertNotInCriticalSection(context);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-05-21 20:47:19 +02:00
|
|
|
/* isReset must be false already */
|
2013-06-27 01:56:03 +02:00
|
|
|
Assert(!context->isReset);
|
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
ret = context->methods->realloc(context, pointer, size);
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
if (unlikely(ret == NULL))
|
2016-03-13 06:21:07 +01:00
|
|
|
{
|
|
|
|
MemoryContextStats(TopMemoryContext);
|
2015-01-29 16:23:38 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
errmsg("out of memory"),
|
Improve out-of-memory error reports by including memory context name.
Add the target context's name to the errdetail field of "out of memory"
errors in mcxt.c. Per discussion, this seems likely to be useful to
help narrow down the cause of a reported failure, and it costs little.
Also, now that context names are required to be compile-time constants
in all cases, there's little reason to be concerned about security
issues from exposing these names to users. (Because of such concerns,
we are *not* including the context "ident" field.)
In passing, add unlikely() markers to the allocation-failed tests,
just to be sure the compiler is on the right page about that.
Also, in palloc and friends, copy CurrentMemoryContext into a local
variable, as that's almost surely cheaper to reference than a global.
Discussion: https://postgr.es/m/1099.1522285628@sss.pgh.pa.us
2018-03-30 19:53:33 +02:00
|
|
|
errdetail("Failed on request of size %zu in memory context \"%s\".",
|
|
|
|
size, context->name)));
|
2016-03-13 06:21:07 +01:00
|
|
|
}
|
2015-01-29 16:23:38 +01:00
|
|
|
|
2013-06-27 02:00:08 +02:00
|
|
|
VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
|
2011-05-21 20:47:19 +02:00
|
|
|
|
2013-06-27 01:56:03 +02:00
|
|
|
return ret;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-05-21 04:23:30 +02:00
|
|
|
/*
|
2000-06-28 05:33:33 +02:00
|
|
|
* MemoryContextStrdup
|
|
|
|
* Like strdup(), but allocate from the specified context
|
2000-05-21 04:23:30 +02:00
|
|
|
*/
|
2000-06-28 05:33:33 +02:00
|
|
|
char *
|
|
|
|
MemoryContextStrdup(MemoryContext context, const char *string)
|
2000-05-21 04:23:30 +02:00
|
|
|
{
|
2000-06-28 05:33:33 +02:00
|
|
|
char *nstr;
|
|
|
|
Size len = strlen(string) + 1;
|
2000-05-21 04:23:30 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
nstr = (char *) MemoryContextAlloc(context, len);
|
2000-05-21 04:23:30 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
memcpy(nstr, string, len);
|
|
|
|
|
|
|
|
return nstr;
|
2000-05-21 04:23:30 +02:00
|
|
|
}
|
2004-08-08 08:44:36 +02:00
|
|
|
|
Create libpgcommon, and move pg_malloc et al to it
libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines. We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.
The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.
At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly. To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc(). This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.
This lets us clean up some places that were already with
localized hacks.
Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that. libpgcommon infrastructure was authored by Álvaro.
2013-02-12 14:33:40 +01:00
|
|
|
char *
|
|
|
|
pstrdup(const char *in)
|
|
|
|
{
|
|
|
|
return MemoryContextStrdup(CurrentMemoryContext, in);
|
|
|
|
}
|
|
|
|
|
2008-06-28 18:45:22 +02:00
|
|
|
/*
|
|
|
|
* pnstrdup
|
|
|
|
* Like pstrdup(), but append null byte to a
|
|
|
|
* not-necessarily-null-terminated input string.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
pnstrdup(const char *in, Size len)
|
|
|
|
{
|
2017-10-10 00:20:42 +02:00
|
|
|
char *out;
|
2008-06-28 18:45:22 +02:00
|
|
|
|
2017-10-10 23:42:16 +02:00
|
|
|
len = strnlen(in, len);
|
2017-10-10 00:20:42 +02:00
|
|
|
|
|
|
|
out = palloc(len + 1);
|
2008-06-28 18:45:22 +02:00
|
|
|
memcpy(out, in, len);
|
|
|
|
out[len] = '\0';
|
2017-10-10 00:20:42 +02:00
|
|
|
|
2008-06-28 18:45:22 +02:00
|
|
|
return out;
|
|
|
|
}
|
2017-02-27 14:30:06 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make copy of string with all trailing newline characters removed.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
pchomp(const char *in)
|
|
|
|
{
|
|
|
|
size_t n;
|
|
|
|
|
|
|
|
n = strlen(in);
|
|
|
|
while (n > 0 && in[n - 1] == '\n')
|
|
|
|
n--;
|
|
|
|
return pnstrdup(in, n);
|
|
|
|
}
|