agora inbox for pgsql-hackers@postgresql.org  
help / color / mirror / Atom feed
[PATCH v1 4/5] Allow to resize shared memory without restart
425+ messages / 2 participants
[nested] [flat]

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v1 4/5] Allow to resize shared memory without restart
@ 2024-10-16 18:24  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2024-10-16 18:24 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Size for every shared memory slot is recalculated based on the new
NBuffers, and extended using mremap. After allocating new space, new
shared structures (buffer blocks, descriptors, etc) are allocated as
needed. Here is how it looks like after raising shared_buffers from 128
MB to 512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v2 5/6] Allow to resize shared memory without restart
@ 2025-02-20 20:12  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-02-20 20:12 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a global
Barrier to coordinate backends that simultaneously change
shared_buffers, and pieces in shared memory to coordinate backends that
are too late to the party for some reason.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier. Afterwards it does shared memory
  resize itself.

* All the backends, that participate in ProcSignal mechanism,
  recalculate shared memory size based on the new NBuffers and extend it
  using mremap.

* When finished, a backend waits on a global ShmemControl barrier,
  untill all backends will be finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all backends are using new value, one backend will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f5a2bd04000-7f5a32e52000  /dev/zero (deleted)
    7f5a39252000-7f5a4030e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d7ba000  /dev/zero (deleted)
    7f5a53bba000-7f5a5ad26000  /dev/zero (deleted)
    7f5a9ad26000-7f5aa9d94000  /dev/zero (deleted)
    ^ buffers mapping, ~240 MB
    7f5d29d94000-7f5d30e00000  /dev/zero (deleted)

    -- 512 MB
    7f5a2bd04000-7f5a33274000  /dev/zero (deleted)
    7f5a39252000-7f5a4057e000  /dev/zero (deleted)
    7f5a4670e000-7f5a4d9fa000  /dev/zero (deleted)
    7f5a53bba000-7f5a5b1a6000  /dev/zero (deleted)
    7f5a9ad26000-7f5ac1f14000  /dev/zero (deleted)
    ^ buffers mapping, ~625 MB
    7f5d29d94000-7f5d30f80000  /dev/zero (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v4 6/8] Allow to resize shared memory without restart
@ 2025-04-06 14:47  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-04-06 14:47 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers and extend it using mremap. One elected process signals the
  postmaster to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f90cde00000-7f90d4fa6000  /dev/zero (deleted)
    7f90d4fa6000-7f914de00000
    7f914de00000-7f915cfa8000  /dev/zero (deleted)
    ^ buffers mapping, ~241 MB
    7f915cfa8000-7f944de00000
    7f944de00000-7f94550a8000  /dev/zero (deleted)
    7f94550a8000-7f94cde00000
    7f94cde00000-7f94d4fe8000  /dev/zero (deleted)
    7f94d4fe8000-7f954de00000
    7f954de00000-7f9554ff6000  /dev/zero (deleted)
    7f9554ff6000-7f958de00000
    7f958de00000-7f959508a000  /dev/zero (deleted)
    7f959508a000-7f95cde00000

    -- 512 MB
    7f90cde00000-7f90d5126000  /dev/zero (deleted)
    7f90d5126000-7f914de00000
    7f914de00000-7f9175128000  /dev/zero (deleted)
    ^ buffers mapping, ~627 MB
    7f9175128000-7f944de00000
    7f944de00000-7f9455528000  /dev/zero (deleted)
    7f9455528000-7f94cde00000
    7f94cde00000-7f94d5228000  /dev/zero (deleted)
    7f94d5228000-7f954de00000
    7f954de00000-7f9555266000  /dev/zero (deleted)
    7f9555266000-7f958de00000
    7f958de00000-7f95954aa000  /dev/zero (deleted)
    7f95954aa000-7f95cde00000

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v5 07/10] Allow to resize shared memory without restart
@ 2025-06-17 12:16  Dmitrii Dolgov <9erthalion6@gmail.com>
  0 siblings, 0 replies; 425+ messages in thread

From: Dmitrii Dolgov @ 2025-06-17 12:16 UTC (permalink / raw)

Add assing hook for shared_buffers to resize shared memory using space,
introduced in the previous commits without requiring PostgreSQL restart.
Essentially the implementation is based on two mechanisms: a
ProcSignalBarrier is used to make sure all processes are starting the
resize procedure simultaneously, and a global Barrier is used to
coordinate after that and make sure all finished processes are waiting
for others that are in progress.

The resize process looks like this:

* The GUC assign hook sets a flag to let the Postmaster know that resize
  was requested.

* Postmaster verifies the flag in the event loop, and starts the resize
  by emitting a ProcSignal barrier.

* All processes, that participate in ProcSignal mechanism, begin to
  process ProcSignal barrier. First a process waits until all processes
  have confirmed they received the message and can start simultaneously.

* Every process recalculates shared memory size based on the new
  NBuffers, adjusts its size using ftruncate and adjust reservation
  permissions with mprotect. One elected process signals the postmaster
  to do the same.

* When finished, every process waits on a global ShmemControl barrier,
  untill all others are finished as well. This way we ensure three
  stages with clear boundaries: before the resize, when all processes
  use old NBuffers; during the resize, when processes have mix of old
  and new NBuffers, and wait until it's done; after the resize, when all
  processes use new NBuffers.

* After all processes are using new value, one of them will initialize
  new shared structures (buffer blocks, descriptors, etc) as needed and
  broadcast new value of NBuffers via ShmemControl in shared memory.
  Other backends are waiting for this operation to finish as well. Then
  the barrier is lifted and everything goes as usual.

Since resizing takes time, we need to take into account that during that time:

- New backends can be spawned. They will check status of the barrier
  early during the bootstrap, and wait until everything is over to work
  with the new NBuffers value.

- Old backends can exit before attempting to resize. Synchronization
  used between backends relies on ProcSignalBarrier and waits for all
  participants received the message at the beginning to gather all
  existing backends.

- Some backends might be blocked and not responsing either before or
  after receiving the message. In the first case such backend still
  have ProcSignalSlot and should be waited for, in the second case
  shared barrier will make sure we still waiting for those backends. In
  any case there is an unbounded wait.

- Backends might join barrier in disjoint groups with some time in
  between. That means that relying only on the shared dynamic barrier is
  not enough -- it will only synchronize resize procedure withing those
  groups. That's why we wait first for all participants of ProcSignal
  mechanism who received the message.

Here is how it looks like after raising shared_buffers from 128 MB to
512 MB and calling pg_reload_conf():

    -- 128 MB
    7f87909fc000-7f8798248000 rw-s /memfd:strategy (deleted)
    7f8798248000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a4e84000 rw-s /memfd:checkpoint (deleted)
    7f87a4e84000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1b42000 rw-s /memfd:iocv (deleted)
    7f87b1b42000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cb59c000 rw-s /memfd:descriptors (deleted)
    7f87cb59c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f87ece38000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~247 MB
    7f87ece38000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~2210 MB
    7f8877066000-7f887e7d0000 rw-s /memfd:main (deleted)
    7f887e7d0000-7f8890a00000 ---s /memfd:main (deleted)

    -- 512 MB
    7f87909fc000-7f879866a000 rw-s /memfd:strategy (deleted)
    7f879866a000-7f879d6ca000 ---s /memfd:strategy (deleted)
    7f879d6ca000-7f87a50f4000 rw-s /memfd:checkpoint (deleted)
    7f87a50f4000-7f87aa398000 ---s /memfd:checkpoint (deleted)
    7f87aa398000-7f87b1d82000 rw-s /memfd:iocv (deleted)
    7f87b1d82000-7f87c3d32000 ---s /memfd:iocv (deleted)
    7f87c3d32000-7f87cba1c000 rw-s /memfd:descriptors (deleted)
    7f87cba1c000-7f87dd6cc000 ---s /memfd:descriptors (deleted)
    7f87dd6cc000-7f8804fb8000 rw-s /memfd:buffers (deleted)
    ^ buffers content, ~632 MB
    7f8804fb8000-7f8877066000 ---s /memfd:buffers (deleted)
    ^ reserved space, ~1824 MB
    7f8877066000-7f887e950000 rw-s /memfd:main (deleted)
    7f887e950000-7f8890a00000 ---s /memfd:main (deleted)

The implementation supports only increasing of shared_buffers. For
decreasing the value a similar procedure is needed. But the buffer
blocks with data have to be drained first, so that the actual data set
fits into the new smaller space.



^ permalink  raw  reply  [nested|flat] 425+ messages in thread

* [PATCH v47 8/9] Error out any process that would block at REPACK
@ 2026-03-25 19:35  Álvaro Herrera <alvherre@kurilemu.de>
  0 siblings, 0 replies; 425+ messages in thread

From: Álvaro Herrera @ 2026-03-25 19:35 UTC (permalink / raw)

Any process waiting on REPACK to release its lock would actually cause
it to deadlock when it tries to upgrade its lock to AEL, losing all work
done to that point.  We avoid this by teaching the deadlock detector to
raise an error when this condition is detected.
---
 src/backend/commands/repack.c                 | 52 ++++++++----
 src/backend/storage/lmgr/deadlock.c           | 15 ++++
 src/include/storage/proc.h                    |  6 +-
 src/test/modules/injection_points/Makefile    |  1 +
 .../expected/repack_deadlock.out              | 63 ++++++++++++++
 src/test/modules/injection_points/meson.build |  1 +
 .../specs/repack_deadlock.spec                | 83 +++++++++++++++++++
 7 files changed, 202 insertions(+), 19 deletions(-)
 create mode 100644 src/test/modules/injection_points/expected/repack_deadlock.out
 create mode 100644 src/test/modules/injection_points/specs/repack_deadlock.spec

diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index 9c807f75d71..3acb2e1d2ba 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -276,6 +276,16 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 	/* Determine the lock mode to use. */
 	lockmode = RepackLockLevel((params.options & CLUOPT_CONCURRENT) != 0);
 
+	/*
+	 * If in concurrent mode, set the PROC_IN_CONCURRENT_REPACK flag.  This
+	 * makes the deadlock checker cause anyone that would conflict with us
+	 * to error out.  It's important to set this flag ahead of actually locking
+	 * the relation; it won't of course affect anyone until we do have a lock
+	 * that others can conflict with.
+	 */
+	if ((params.options & CLUOPT_CONCURRENT) != 0)
+		MyProc->statusFlags |= PROC_IN_CONCURRENT_REPACK;
+
 	/*
 	 * If a single relation is specified, process it and we're done ... unless
 	 * the relation is a partitioned table, in which case we fall through.
@@ -476,11 +486,8 @@ RepackLockLevel(bool concurrent)
  * If indexOid is InvalidOid, the table will be rewritten in physical order
  * instead of index order.
  *
- * Note that, in the concurrent case, the function releases the lock at some
- * point, in order to get AccessExclusiveLock for the final steps (i.e. to
- * swap the relation files). To make things simpler, the caller should expect
- * OldHeap to be closed on return, regardless CLUOPT_CONCURRENT. (The
- * AccessExclusiveLock is kept till the end of the transaction.)
+ * On return, OldHeap is closed but locked with AccessExclusiveLock - the lock
+ * will be released at end of the transaction.
  *
  * 'cmd' indicates which command is being executed, to be used for error
  * messages.
@@ -512,10 +519,12 @@ cluster_rel(RepackCommand cmd, Relation OldHeap, Oid indexOid,
 		/*
 		 * Make sure we're not in a transaction block.
 		 *
-		 * The reason is that repack_setup_logical_decoding() could deadlock
-		 * if there's an XID already assigned.  It would be possible to run in
-		 * a transaction block if we had no XID, but this restriction is
-		 * simpler for users to understand and we don't lose anything.
+		 * The reason is that repack_setup_logical_decoding() could wait
+		 * indefinitely for our XID to complete. (The deadlock detector would
+		 * not recognize it because we'd be waiting for ourselves, i.e. no
+		 * real lock conflict.) It would be possible to run in a transaction
+		 * block if we had no XID, but this restriction is simpler for users
+		 * to understand and we don't lose anything.
 		 */
 		PreventInTransactionBlock(isTopLevel, "REPACK (CONCURRENTLY)");
 
@@ -998,10 +1007,8 @@ rebuild_relation(Relation OldHeap, Relation index, bool verbose,
 		 * Note that the worker has to wait for all transactions with XID
 		 * already assigned to finish. If some of those transactions is
 		 * waiting for a lock conflicting with ShareUpdateExclusiveLock on our
-		 * table (e.g.  it runs CREATE INDEX), we can end up in a deadlock.
-		 * Not sure this risk is worth unlocking/locking the table (and its
-		 * clustering index) and checking again if it's still eligible for
-		 * REPACK CONCURRENTLY.
+		 * table (e.g. it runs CREATE INDEX), it should encounter ERROR in the
+		 * deadlock checking code.
 		 */
 		start_repack_decoding_worker(tableOid);
 
@@ -3090,7 +3097,16 @@ rebuild_relation_finish_concurrent(Relation NewHeap, Relation OldHeap,
 		LockRelationOid(OldHeap->rd_rel->reltoastrelid, AccessExclusiveLock);
 
 	/*
-	 * Tuples and pages of the old heap will be gone, but the heap will stay.
+	 * Now that we have all access-exclusive locks on all relations, we no
+	 * longer want other processes to error out when trying to acquire a
+	 * conflicting lock.  Therefore, unset our flag.
+	 */
+	MyProc->statusFlags &= ~PROC_IN_CONCURRENT_REPACK;
+
+	/*
+	 * Tuples and pages of the old heap will be gone, but the heap itself will
+	 * stay.  In order for predicate locks to continue to work, convert them
+	 * to relation-level locks.  We do this both for table and indexes.
 	 */
 	TransferPredicateLocksToHeapRelation(OldHeap);
 	foreach_ptr(RelationData, index, indexrels)
@@ -3287,9 +3303,11 @@ start_repack_decoding_worker(Oid relid)
 
 	/*
 	 * The decoding setup must be done before the caller can have XID assigned
-	 * for any reason, otherwise the worker might end up in a deadlock,
-	 * waiting for the caller's transaction to end. Therefore wait here until
-	 * the worker indicates that it has the logical decoding initialized.
+	 * for any reason, otherwise the worker might end up waiting for the
+	 * caller's transaction to end. (Deadlock detector does not consider this
+	 * a conflict because the worker is in the same locking group as the
+	 * backend that launched it.) Therefore wait here until the worker
+	 * indicates that it has the logical decoding initialized.
 	 */
 	ConditionVariablePrepareToSleep(&shared->cv);
 	for (;;)
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index b8962d875b6..3d3ec0da111 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -620,6 +620,21 @@ FindLockCycleRecurseMember(PGPROC *checkProc,
 						proc->statusFlags & PROC_IS_AUTOVACUUM)
 						blocking_autovacuum_proc = proc;
 
+					/*
+					 * Similarly, if we note that we're blocked by some process
+					 * running REPACK (CONCURRENTLY), just fail.  That process
+					 * is going to upgrade its lock at some point, and it would
+					 * be inappropriate for any other process to cause that
+					 * to fail.
+					 */
+					if (checkProc == MyProc &&
+						proc->statusFlags & PROC_IN_CONCURRENT_REPACK)
+						ereport(ERROR,
+								errcode(ERRCODE_OBJECT_IN_USE),
+								errmsg("could not wait for concurrent REPACK"),
+								errdetail("Process %d waits for REPACK running on process %d",
+									   MyProc->pid, proc->pid));
+
 					/* We're done looking at this proclock */
 					break;
 				}
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 1dad125706e..8ad9718f3d6 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -69,10 +69,12 @@ struct XidCache
 #define		PROC_AFFECTS_ALL_HORIZONS	0x20	/* this proc's xmin must be
 												 * included in vacuum horizons
 												 * in all databases */
+#define		PROC_IN_CONCURRENT_REPACK	0x40	/* REPACK (CONCURRENTLY) */
 
-/* flags reset at EOXact */
+/* flags reset at EOXact.  A bit of a misnomer ... */
 #define		PROC_VACUUM_STATE_MASK \
-	(PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND)
+	(PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND | \
+	 PROC_IN_CONCURRENT_REPACK)
 
 /*
  * Xmin-related flags. Make sure any flags that affect how the process' Xmin
diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile
index 2cd7d87c533..f7663859fe2 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -15,6 +15,7 @@ REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
 ISOLATION = basic \
 	    inplace \
 	    repack \
+	    repack_deadlock \
 	    repack_toast \
 	    syscache-update-pruned \
 	    heap_lock_update
diff --git a/src/test/modules/injection_points/expected/repack_deadlock.out b/src/test/modules/injection_points/expected/repack_deadlock.out
new file mode 100644
index 00000000000..a86e4767536
--- /dev/null
+++ b/src/test/modules/injection_points/expected/repack_deadlock.out
@@ -0,0 +1,63 @@
+Parsed test spec with 2 sessions
+
+starting permutation: wait_before_lock add_column wakeup_before_lock check1
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step wait_before_lock: 
+	REPACK (CONCURRENTLY) repack_deadlock USING INDEX repack_deadlock_pkey;
+ <waiting ...>
+step add_column: 
+	alter table repack_deadlock add column noise text;
+ <waiting ...>
+step add_column: <... completed>
+ERROR:  could not wait for concurrent REPACK
+step wakeup_before_lock: 
+	SELECT injection_points_wakeup('repack-concurrently-before-lock');
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step wait_before_lock: <... completed>
+step check1: 
+	INSERT INTO relfilenodes(node)
+	SELECT relfilenode FROM pg_class WHERE relname='repack_deadlock';
+
+	SELECT count(DISTINCT node) FROM relfilenodes;
+
+	SELECT i, j FROM repack_deadlock ORDER BY i, j;
+
+	INSERT INTO data_s1(i, j)
+	SELECT i, j FROM repack_deadlock;
+
+	SELECT count(*)
+	FROM data_s1 d1 FULL JOIN data_s2 d2 USING (i, j)
+	WHERE d1.i ISNULL OR d2.i ISNULL;
+
+count
+-----
+    1
+(1 row)
+
+i|j
+-+-
+1|1
+2|2
+3|3
+4|4
+(4 rows)
+
+count
+-----
+    4
+(1 row)
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build
index a414abb924b..1cd88d6db65 100644
--- a/src/test/modules/injection_points/meson.build
+++ b/src/test/modules/injection_points/meson.build
@@ -46,6 +46,7 @@ tests += {
       'basic',
       'inplace',
       'repack',
+      'repack_deadlock',
       'repack_toast',
       'syscache-update-pruned',
       'heap_lock_update',
diff --git a/src/test/modules/injection_points/specs/repack_deadlock.spec b/src/test/modules/injection_points/specs/repack_deadlock.spec
new file mode 100644
index 00000000000..9d23a6588c2
--- /dev/null
+++ b/src/test/modules/injection_points/specs/repack_deadlock.spec
@@ -0,0 +1,83 @@
+# Test REPACK with a concurrent transaction that would cause a deadlock
+setup
+{
+	CREATE EXTENSION injection_points;
+
+	CREATE TABLE repack_deadlock(i int PRIMARY KEY, j int);
+	INSERT INTO repack_deadlock(i, j) VALUES (1, 1), (2, 2), (3, 3), (4, 4);
+
+	CREATE TABLE relfilenodes(node oid);
+
+	CREATE TABLE data_s1(i int, j int);
+	CREATE TABLE data_s2(i int, j int);
+}
+
+teardown
+{
+	DROP TABLE repack_deadlock;
+	DROP EXTENSION injection_points;
+
+	DROP TABLE relfilenodes;
+	DROP TABLE data_s1;
+	DROP TABLE data_s2;
+}
+
+session s1
+setup
+{
+	SELECT injection_points_set_local();
+	SELECT injection_points_attach('repack-concurrently-before-lock', 'wait');
+}
+# Perform the initial load and wait for s2 to do some data changes.
+step wait_before_lock
+{
+	REPACK (CONCURRENTLY) repack_deadlock USING INDEX repack_deadlock_pkey;
+}
+# Check the table from the perspective of s1.
+#
+# Besides the contents, we also check that relfilenode has changed.
+
+# Have each session write the contents into a table and use FULL JOIN to check
+# if the outputs are identical.
+step check1
+{
+	INSERT INTO relfilenodes(node)
+	SELECT relfilenode FROM pg_class WHERE relname='repack_deadlock';
+
+	SELECT count(DISTINCT node) FROM relfilenodes;
+
+	SELECT i, j FROM repack_deadlock ORDER BY i, j;
+
+	INSERT INTO data_s1(i, j)
+	SELECT i, j FROM repack_deadlock;
+
+	SELECT count(*)
+	FROM data_s1 d1 FULL JOIN data_s2 d2 USING (i, j)
+	WHERE d1.i ISNULL OR d2.i ISNULL;
+}
+teardown
+{
+	SELECT injection_points_detach('repack-concurrently-before-lock');
+}
+
+session s2
+# Change the existing data. UPDATE changes both key and non-key columns. Also
+# update one row twice to test whether tuple version generated by this session
+# can be found.
+step add_column
+{
+	alter table repack_deadlock add column noise text;
+}
+
+step wakeup_before_lock
+{
+	SELECT injection_points_wakeup('repack-concurrently-before-lock');
+}
+
+# Test if data changes introduced while one session is performing REPACK
+# CONCURRENTLY find their way into the table.
+permutation
+	wait_before_lock
+	add_column
+	wakeup_before_lock
+	check1
-- 
2.47.3


--2fxmamo6mu2qbxgv
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
	filename="v47-0009-Teach-snapshot-builder-to-skip-transactions-runn.patch"



^ permalink  raw  reply  [nested|flat] 425+ messages in thread


end of thread, other threads:[~2026-03-25 19:35 UTC | newest]

Thread overview: 425+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2024-10-16 18:24 [PATCH v1 4/5] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-02-20 20:12 [PATCH v2 5/6] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-04-06 14:47 [PATCH v4 6/8] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2025-06-17 12:16 [PATCH v5 07/10] Allow to resize shared memory without restart Dmitrii Dolgov <9erthalion6@gmail.com>
2026-03-25 19:35 [PATCH v47 8/9] Error out any process that would block at REPACK Álvaro Herrera <alvherre@kurilemu.de>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox