Re: pgstat vs aset

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: Andres Freund <andres(at)anarazel(dot)de>
Cc: pgsql-hackers(at)postgresql(dot)org, Nathan Bossart <nathandbossart(at)gmail(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Alexander Lakhin <exclusion(at)gmail(dot)com>, Sami Imseih <samimseih(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, Treat <rob(at)xzilla(dot)net>, satyanarlapuram(at)gmail(dot)com, tndrwang(at)gmail(dot)com
Subject: Re: pgstat vs aset
Date: 2026-04-09 01:51:26
Message-ID: A79BDDB6-4594-4C24-97AF-D515E261DEDC@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Apr 9, 2026, at 07:04, Andres Freund <andres(at)anarazel(dot)de> wrote:
>
> Hi,
>
> In [1] I looked at pgstat memory usage after sort of a complaint by Nathan.
> The conversion of "PgStat Shared Ref" to slab seems like an improvement we
> obviously should make [2].
>
> In the email I also showed how much CacheMemoryContext using a lot of memory
> after doing a database wide VACUUM (with ~100k tables), not very surprising.
>
>
> I didn't immediately look at the next few entries:
> ┌────────────────────────┬─────────────┬───────────────┬────────────┬─────────────┬────────────┐
> │ name │ total_bytes │ total_nblocks │ free_bytes │ free_chunks │ used_bytes │
> ├────────────────────────┼─────────────┼───────────────┼────────────┼─────────────┼────────────┤
> │ CacheMemoryContext │ 168820784 │ 31 │ 2363064 │ 33 │ 166457720 │
> │ PgStat Pending │ 27983872 │ 3419 │ 27846912 │ 112699 │ 136960 │
> │ smgr relation table │ 16777216 │ 12 │ 2797592 │ 50 │ 13979624 │
> │ MdSmgr │ 8388608 │ 11 │ 3475256 │ 1 │ 4913352 │
> │ PgStat Shared Ref │ 5767344 │ 88 │ 19712 │ 352 │ 5747632 │
> │ PgStat Shared Ref Hash │ 4195376 │ 2 │ 712 │ 0 │ 4194664 │
> │ Relcache by OID │ 4194304 │ 10 │ 57448 │ 24 │ 4136856 │
> │ TopMemoryContext │ 173264 │ 7 │ 32968 │ 79 │ 140296 │
> └────────────────────────┴─────────────┴───────────────┴────────────┴─────────────┴────────────┘
>
> When I did I was quite surprised to see "PgStat Pending" using so much, as it
> should all be freed after the stats have been submitted, a few seconds later
> at most.
>
> After a moment of worry about having introduced a leak, and adding the
> necessary columns to see more information, it's clear that all the memory was
> actually freed. It's just that we don't ever free aset blocks, even if all the
> constituent memory has been freed. So the overall context size doesn't shrink.
>
> That seems decidedly not great.
>
> I wonder how bad it would be to teach aset to recognize this situation.
>
> But I think for this use case we actually have a more fitting memory context
> type for this workload, i.e. GenerationContext. With that the size after the
> same vacuum is
>
> │ PgStat Pending │ 134144 │ 3 │ 133848 │ 0 │ 296 │
>
> Seems like a fairly obvious change.
>
>
> My local experimental changes attached.
>
>
> Greetings,
>
> Andres Freund
>
> [1] https://postgr.es/m/fcvnawwq32mamvf66q5i3sk73xudxz5corqlgqljtocepspjps%40ypvl6yjzy5xk
> [2] It's a big enough saving that I'm kinda wondering about whether we should
> try to sneak it into 19.
> <pgstat-memory.diff>

I tested this patch by creating a large number of tables and then running VACUUM.

Before the patch:
```
evantest=# select name, total_bytes, free_bytes, used_bytes, total_nblocks, free_chunks
from pg_backend_memory_contexts
where name in ('PgStat Pending', 'PgStat Shared Ref', 'PgStat Shared Ref Hash')
order by name;
name | total_bytes | free_bytes | used_bytes | total_nblocks | free_chunks
------------------------+-------------+------------+------------+---------------+-------------
PgStat Pending | 16384 | 8368 | 8016 | 5 | 8
PgStat Shared Ref | 8192 | 3672 | 4520 | 4 | 2
PgStat Shared Ref Hash | 9280 | 704 | 8576 | 2 | 0
(3 rows)

evantest=# vacuum;
VACUUM
evantest=#
evantest=# select name, total_bytes, free_bytes, used_bytes, total_nblocks, free_chunks
from pg_backend_memory_contexts
where name in ('PgStat Pending', 'PgStat Shared Ref', 'PgStat Shared Ref Hash’)
order by name;
name | total_bytes | free_bytes | used_bytes | total_nblocks | free_chunks
------------------------+-------------+------------+------------+---------------+-------------
PgStat Pending | 65536 | 64896 | 640 | 11 | 244
PgStat Shared Ref | 8142848 | 79328 | 8063520 | 997 | 1987
PgStat Shared Ref Hash | 4195392 | 704 | 4194688 | 2 | 0
(3 rows)
```

After the patch:
```
evantest=# select name, total_bytes, free_bytes, used_bytes, total_nblocks, free_chunks
from pg_backend_memory_contexts
where name in ('PgStat Pending', 'PgStat Shared Ref', 'PgStat Shared Ref Hash’)
order by name;
name | total_bytes | free_bytes | used_bytes | total_nblocks | free_chunks
------------------------+-------------+------------+------------+---------------+-------------
PgStat Pending | 8192 | 3360 | 4832 | 4 | 0
PgStat Shared Ref | 16802 | 13536 | 3266 | 1 | 188
PgStat Shared Ref Hash | 9280 | 704 | 8576 | 2 | 0
(3 rows)

evantest=#
evantest=# vacuum;
VACUUM
evantest=#
evantest=#
evantest=#
evantest=# select name, total_bytes, free_bytes, used_bytes, total_nblocks, free_chunks
from pg_backend_memory_contexts
where name in ('PgStat Pending', 'PgStat Shared Ref', 'PgStat Shared Ref Hash’)
order by name;
name | total_bytes | free_bytes | used_bytes | total_nblocks | free_chunks
------------------------+-------------+------------+------------+---------------+-------------
PgStat Pending | 37888 | 37592 | 296 | 3 | 0
PgStat Shared Ref | 7274914 | 3672 | 7271242 | 444 | 51
PgStat Shared Ref Hash | 4195392 | 704 | 4194688 | 2 | 0
(3 rows)
```

For PgStat Pending, total_bytes went from about 64kB down to about 36kB.

For PgStat Shared Ref, total_bytes went from about 8MB down to about 7MB.

As a comparison point, PgStat Shared Ref Hash showed no change before and after the patch.

So this does show improvement to me.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message SATYANARAYANA NARLAPURAM 2026-04-09 02:03:31 Bug: WAIT FOR LSN crashes with assertion failure inside PL/pgSQL DO blocks and procedures
Previous Message Xuneng Zhou 2026-04-09 01:09:08 Re: Use proc_exit() in WalRcvWaitForStartPosition