Thread

  1. Re: Enhancing Memory Context Statistics Reporting

    Rahila Syed <rahilasyed90@gmail.com> — 2025-11-25T07:20:44Z

    Hi Daniel,
    
    Thank you for your comments. Please find attached v41 with all the comments
    addressed.
    
    
    >
    > +#include "access/twophase.h"
    > +#include "catalog/pg_authid_d.h"
    > ...
    > +#include "utils/acl.h"
    > Are these actually required to be included?
    >
    >
    Removed these.
    
    
    > -       MemoryContextId *entry;
    > +       MemoryStatsContextId *entry;
    > Why is this needed?  MemoryStatsContextId is identical to MemoryContextId
    > and
    > is too only used in mcxtfuncs.c so there is no need to expose it in
    > memutils.h.
    > Can't you just use MemoryContextId everywhere or am I missing something?
    >
    >
    MemoryContextId has been renamed to MemoryStatsContextId for better
    code readability.  I removed the leftover MemoryContextId definition.
    Also, I moved it out of memutils.h. Did the same with some other structures
    and definitions which were only used in mcxtfuncs.c
    
    
    > +#define CLIENT_KEY_SIZE 64
    > +
    > +static LWLock *client_keys_lock = NULL;
    > +static int *client_keys = NULL;
    > +static dshash_table *MemoryStatsDsHash = NULL;
    > +static dsa_area *MemoryStatsDsaArea = NULL;
    > These new additions have in some cases too generic names (client_keys etc)
    > and
    > they all lack comments explaining why they're needed.  Maybe a leading
    > block
    > comment explaining they are used for process memory context reporting, and
    > then
    > inline comments on each with their use?
    >
    >
    Added comments.
    
    
    > +#define CLIENT_KEY_SIZE 64
    > ...
    > +   char        key[CLIENT_KEY_SIZE];
    > ...
    > +   snprintf(key, sizeof(key), "%d", MyProcNumber);
    > Given that MyProcNumber is an index into the proc array, it seems
    > excessive to
    > use 64 bytes to store it, can't we get away with a small stack allocation?
    >
    
    I agree. Defined it as 32 bytes as MyProcNumber is of size uint32.  Kindly
    let me know if you think it can be reduced further.
    
    
    +    * Retreive the client key for publishing statistics and reset it to -1,
    > s/Retreive/Retrieve/
    >
    
    Fixed.
    
    
    > +   ProcNumber  procNumber = INVALID_PROC_NUMBER;
    > This variable is never accessed before getting re-assigned, so this
    > assignment
    > in the variable definition can be removed per project style.
    >
    >
    >
    Fixed too.
    
    
    > +   InitMaterializedSRF(fcinfo, 0);
    > Can this initialization be postponed till when we know the ResultSetInfo is
    > needed?  While a micro optimization, it seems we can avoid that overhead in
    > case the query errors out?
    >
    >
    Good point. Added this just before the result set is getting populated.
    
    
    > +   if (MemoryStatsDsHash == NULL)
    > +       MemoryStatsDsHash =
    > GetNamedDSHash("memory_context_statistics_dshash", &memctx_dsh_params,
    > &found);
    > Nitpick, but there are a few oversize lines, like this one, which need to
    > be
    > wrapped to match project style.
    >
    >
    I have edited this accordingly.
    
    
    > +   /*
    > +    * XXX. If the process exits without cleaning up its slot, i.e in case
    > of
    > +    * an abrupt crash the client_keys slot won't be reset thus resulting
    > in
    > +    * false negative and WARNING would be thrown in case another process
    > with
    > +    * same slot index is queried for statistics.
    > +    */
    > +   if (client_keys[procNumber] == -1)
    > +       client_keys[procNumber] = MyProcNumber;
    > +   else
    > +   {
    > +       LWLockRelease(client_keys_lock);
    > +       ereport(WARNING,
    > +               errmsg("server process %d is processing previous request",
    > pid));
    > +       PG_RETURN_NULL();
    > +   }
    > AFAICT this mean that a failure to clean up (through a crash for example)
    > can
    > block a future backend from reporting which isn't entirely ideal.  Is there
    > anything we can do to mitigate this?
    >
    >
    Yes, we can reset it when the client times out, as long as we verify that
    the value corresponds
    to our ProcNumber and not another client's request. Fixed accordingly.
    
    
    >
    > +   bool        summary = false;
    > In ProcessGetMemoryContextInterrupt(), can't we just read entry->summary
    > rather
    > than define a local variable and assign it?  We already read lots of other
    > fields from entry directly so it seems more readable to be consistent.
    >
    >
    Fixed.
    
    
    >
    > +   /*
    > +    * Add the count of children contexts which are traversed
    > +    */
    > +   *num_contexts = *num_contexts + ichild;
    > Isn't this really the number of children + the parent context?  ichild
    > starts
    > at one to (AIUI) include the parent context.  Also,
    > MemoryContextStatsCounter
    > should also make sure to set num_contexts to zero before adding to it.
    >
    >
    Yes. Adjusted the comment to match this and set num_contexts to zero.
    
    
    >
    > +#define MAX_MEMORY_CONTEXT_STATS_SIZE (sizeof(MemoryStatsEntry))
    > +#define MAX_MEMORY_CONTEXT_STATS_NUM
    > MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND / MAX_MEMORY_CONTEXT_STATS_SIZE
    > I don't think MAX_MEMORY_CONTEXT_STATS_SIZE adds any value as it's only
    > used
    > once, on the line directly after its definition.  We can just use the
    > expansion
    > of ((sizeof(MemoryStatsEntry)) when defining MAX_MEMORY_CONTEXT_STATS_NUM.
    >
    >
    Fixed.
    
    I've attached the test patch as is, I will clean it up and do further
    improvements to it.
    
    Thank you,
    Rahila Syed