Re: Separate memory contexts for relcache and catcache

From: Ashutosh Bapat <ashutosh(dot)bapat(dot)oss(at)gmail(dot)com>
To: Andres Freund <andres(at)anarazel(dot)de>
Cc: Jeff Davis <pgsql(at)j-davis(dot)com>, Melih Mutlu <m(dot)melihmutlu(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>, torikoshia <torikoshia(at)oss(dot)nttdata(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>
Subject: Re: Separate memory contexts for relcache and catcache
Date: 2024-11-11 11:35:23
Message-ID: CAExHW5sH4NZnHi4S5ai0uFQgfS_R=rts_+LK5JeEQ-dVzwKRfQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Sat, Nov 2, 2024 at 4:18 AM Andres Freund <andres(at)anarazel(dot)de> wrote:
>
>
> > > I've previously proposed creating a type of memory context that's
> > > intended for
> > > places where we never expect to allocate much which allocates from
> > > either a
> > > superior memory context or just from the system allocator and tracks
> > > memory
> > > via linked lists.
> >
> > Why not just use ALLOCSET_SMALL_SIZES?
>
> That helps some, but not *that* much. You still end up with a bunch of partially
> filled blocks. Here's e.g. an excerpt with your patch applied:
>
> │ name │ ident │ type │ level │ path │ total_bytes │ total_nblocks │ free_bytes │ free_chunks │ used_bytes │
> ├──────────────────────────────┼────────────────────────────────────────────────┼──────────┼───────┼───────────────┼─────────────┼───────────────┼────────────┼─────────────┼────────────┤
> │ CacheMemoryContext │ (null) │ AllocSet │ 2 │ {1,19} │ 8192 │ 1 │ 7952 │ 0 │ 240 │
> │ TypCacheContext │ (null) │ AllocSet │ 3 │ {1,19,28} │ 8192 │ 1 │ 4816 │ 0 │ 3376 │
> │ search_path processing cache │ (null) │ AllocSet │ 3 │ {1,19,29} │ 8192 │ 1 │ 5280 │ 7 │ 2912 │
> │ CatCacheContext │ (null) │ AllocSet │ 3 │ {1,19,30} │ 262144 │ 6 │ 14808 │ 0 │ 247336 │
> │ RelCacheContext │ (null) │ AllocSet │ 3 │ {1,19,31} │ 262144 │ 6 │ 8392 │ 2 │ 253752 │
> │ relation rules │ pg_backend_memory_contexts │ AllocSet │ 4 │ {1,19,31,34} │ 8192 │ 4 │ 3280 │ 1 │ 4912 │
> │ index info │ manyrows_pkey │ AllocSet │ 4 │ {1,19,31,35} │ 2048 │ 2 │ 864 │ 1 │ 1184 │
> │ index info │ pg_statistic_ext_relid_index │ AllocSet │ 4 │ {1,19,31,36} │ 2048 │ 2 │ 928 │ 1 │ 1120 │
> │ index info │ pg_class_tblspc_relfilenode_index │ AllocSet │ 4 │ {1,19,31,37} │ 2048 │ 2 │ 440 │ 1 │ 1608 │
>
> (this is a tiny bit misleading as "search_path processing cache" was just moved")
>
> You can quickly see that the various contexts have a decent amount of free
> space, some of their space.
>
> We've already been more aggressive about using separate contets for indexes -
> and in aggregate that memory usage shows up:
>
> postgres[1088243][1]=# SELECT count(*), sum(total_bytes) as total_bytes, sum(total_nblocks) as total_nblocks, sum(free_bytes) free_bytes, sum(free_chunks) as free_chunks, sum(used_bytes) used_bytes FROM pg_backend_memory_contexts WHERE path @> (SELECT path FROM pg_backend_memory_contexts WHERE name = 'CacheMemoryContext') and name = 'index info'
> ┌───────┬─────────────┬───────────────┬────────────┬─────────────┬────────────┐
> │ count │ total_bytes │ total_nblocks │ free_bytes │ free_chunks │ used_bytes │
> ├───────┼─────────────┼───────────────┼────────────┼─────────────┼────────────┤
> │ 87 │ 162816 │ 144 │ 48736 │ 120 │ 114080 │
> └───────┴─────────────┴───────────────┴────────────┴─────────────┴────────────┘
>
>
>
> And it's not just the partially filled blocks that are an "issue", it's also
> the freelists that are much less likely to be used soon if they're split very
> granularly. Often we'll end up with memory in freelists that are created while
> building some information that then will not be used again.
>
>
> Without your patch:
> ┌────────────────────┬────────────────────────────────────────────────┬──────────┬───────┬────────────┬─────────────┬───────────────┬────────────┬─────────────┬────────────┐
> │ name │ ident │ type │ level │ path │ total_bytes │ total_nblocks │ free_bytes │ free_chunks │ used_bytes │
> ├────────────────────┼────────────────────────────────────────────────┼──────────┼───────┼────────────┼─────────────┼───────────────┼────────────┼─────────────┼────────────┤
> │ CacheMemoryContext │ (null) │ AllocSet │ 2 │ {1,17} │ 524288 │ 7 │ 75448 │ 0 │ 448840 │
> │ relation rules │ pg_backend_memory_contexts │ AllocSet │ 3 │ {1,17,27} │ 8192 │ 4 │ 3472 │ 4 │ 4720 │
> ...

If these caches are not used at all, this might be a problem. But I
think the applications which use TextSearchCacheContext, let's say,
are likely to use it so frequently that the free chunks will be
recycled. So, I don't know whether that will be a huge problem with
partial blocks and freelists.

However, we agree that it's generally good to have (at least some)
specific contexts as children of cache memory context. It will be good
to move ahead with the ones we all agree for now. Looking at all the
emails, those will be CatCacheContext,
RelCacheContext, PlanCacheContext, TypCacheContext. If we go with
fewer context, it will be good not to lose the work Jeff did for other
contexts though. I like those Create*CacheContext() functions. They
identify various specific uses of CacheMemoryContext. In future, if we
think that we need specific contexts for some of those, these will be
the functions where we will create specific contexts. We might need to
change the name of those functions to Get*CacheContext() instead of
Create since they won't create a context right now.

--
Best Wishes,
Ashutosh Bapat

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message jian he 2024-11-11 11:37:50 Re: Virtual generated columns
Previous Message Amit Kapila 2024-11-11 11:11:51 Re: doc: pgevent.dll location