Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w5T6l-003HUD-39 for pgsql-hackers@arkaria.postgresql.org; Wed, 25 Mar 2026 18:37:36 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w5T6k-00FyBx-1i for pgsql-hackers@arkaria.postgresql.org; Wed, 25 Mar 2026 18:37:34 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w5T6k-00FyBm-0O for pgsql-hackers@lists.postgresql.org; Wed, 25 Mar 2026 18:37:34 +0000 Received: from mail-ej1-x62b.google.com ([2a00:1450:4864:20::62b]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w5T6i-000000010t9-2WSf for pgsql-hackers@postgresql.org; Wed, 25 Mar 2026 18:37:33 +0000 Received: by mail-ej1-x62b.google.com with SMTP id a640c23a62f3a-b9825ba7e8dso19656866b.3 for ; Wed, 25 Mar 2026 11:37:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774463851; cv=none; d=google.com; s=arc-20240605; b=iD+wTDXCZoe6Rz2bVhRtIeSW5JyleJ8bbH0fw5k2uVB1jn9rlRTZIf4R/wzGi2bFRb azEt9a8NJ5AsIta2EqdASb4Yt502PhB5k/7gfDX3V4j0q7JVJddr+vqJhc2Y/glZsiUk WeL2f78AFQWoOX4gizq7GJWIJ2roxHeeDCVmJzUH7RQS3RJmQ7rWdta8xRECPIMTQDtS llThb1InAl7B1bv4ZYJr8L3+nbGXjGhY6s5xfoAb/rIPfeFtBYtk+fmdPLpruWQLvP5y W3Sd9sfPrYqXztpKywzynRI4T8JFevDDqWRqnLn1a7Vk4niJVvIXEaGlP2nKSprqqhXY yIqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=C5/qmNkU9Bq5wNnT0ex19CUmbTPFhsUsp6S5Iej2G8o=; fh=7iaTnC64Pnd4KkCgUfD3s8KYLHDWWPJ9NFI+70AeXZo=; b=EwLayUtNMydgP+D4ImobW1cvafR5m1RQy6S8SiACqJuXJ/i9OjD69wJ65tYSdQKP48 zV8jgbTzzOObGpjrSgLfWvgJRzcXmZkpAn5Ul1TW4fxqOQ57TlBb+hvlIW62J1FrAhcS sErjIWNKvcF5qiXQBrJqjdQ05tunE79SW0wwPISH7AWomKeYG/dVKTqO/hWxo3ZAGJFM 9t6IsQ0wTw/+zDw2rraBRZvqzmgfno3YJBsHRROkHrCiD82GxX0z1FUqfzorPI3fsZ7X szz06j+Xc0b+8K0YBtpMpx58cH1WV0L8L9KjmM/ETw8S4mlnHInH9q1O60RLGE+Ac3kw b2Dw==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774463851; x=1775068651; darn=postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=C5/qmNkU9Bq5wNnT0ex19CUmbTPFhsUsp6S5Iej2G8o=; b=sXVz06ePCOyfBsf81FxbdVcEy/DiRCC6KTW/q4bOYBYI9iuyiQhx3SU49IWbcBrNLn JnsxVkIOYmHlEbB6b5BlyHy38k8kTYhPgh7caxTAMBg8NzIUo5xW6yxwN0UK3ADoKCJp iFnRKHaCa0zCTJzSHfQHxzM+asQO2s/Lx3PXkhU55JDN01l+3bel8UlTcgYPl5GgOy5T m0qLTs+A8P/z/ROQsyY+w5XYoWmApp5j8jarAJd/PSjz3EtP75ZglxwrK1ffiF3/YlE9 mjRfFGIp/MXqqEQG64NPoHeBZjGW3sqIm+Ex5wrjWPx2hvA8pQSjGR+WL6bYrl10TLAg HO6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774463851; x=1775068651; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=C5/qmNkU9Bq5wNnT0ex19CUmbTPFhsUsp6S5Iej2G8o=; b=r03NJFKwRGpkfEcH7k5PaDMsm7tixE33MHraW10KPYrnGeRqwL2Zq5Fx9d/ATZ8ieL 4uT7rmK4dK8w4xOdPNLAnI9wODl1CddSuYjPmwYHfj8Im0X1YoQpsCRu3NiUlZ6M2mMI q7GgyQYMkj3HvtYkFbnrDToGLuggp5M78Uynivo5iD5kSkELSns1KHLW5fJ62E+dfORn gF4wxsmTaclaDB68/9vaPgauV61alSa52ajKzE5NvpYRkQYRr93yowNwXu3pW1xkbVVK SSPJeGAVlOtiugIEYwbOvS1liRUNgR1wDNZMqDY/ffLN9smz3nveyOS834IYV1B0pfdn ZVJA== X-Forwarded-Encrypted: i=1; AJvYcCUdiYyO38GX5l0yd8w93GneaORnD3iFaoDQGUc/XKIuloMCtlA6gbz0Erc7MNEabqgekwOO7RRlsvU1D/Ro@postgresql.org X-Gm-Message-State: AOJu0Ywot/6Swb2nllauIrRIubOexymQ69y0HyzvTaYe048ZmLFw2m7z rpCoizp9GSp1iddoZaty2K25faR9AFPY01J9Oa8QbLYAlijVgyT74KiAQGm7wAFyIcYBTkaUaa6 YnRe/o025Ek7cGYPWtcYwlru0Q0O+2lQ= X-Gm-Gg: ATEYQzxNPr/s0oOQ6krnJCKM/RNFAq7rebydbnqmrL4D/AcDxB8MqGSmRjqfezn31aD egzDLQsZsOUyz8K4gagbCvbmozbsbJv86PEBB7k7iqSN5FOAdUAkqarcZMjgUMy49Jz718fehO6 qCNeBGC58QPzLOGDUk5h78RDI7/QRWfoOxRGQBGRBk16R/9SFDv7SkagyUhl6YmKBrOERYeBf8m /K5Y1vWAYd68YsjZqTCnyCXf3V12bkMu1gyIQHbSaEq6Uqq/Ta6HIJoYaTedPzmyTh16KUC4te/ rtzUuYi2WqP4+fXsYlM4FpnZwjqSBTQj1d36Em8= X-Received: by 2002:a17:907:890b:b0:b97:98b5:3767 with SMTP id a640c23a62f3a-b9a5422431emr296417166b.35.1774463850816; Wed, 25 Mar 2026 11:37:30 -0700 (PDT) MIME-Version: 1.0 References: <26c766d6-db0f-43d3-a618-44f8d40a3121@iki.fi> <62b8dc23-8f6a-4cac-91ff-f74bb5bc159a@iki.fi> <8a6799be-bd42-49fb-8914-856c97bb1977@iki.fi> <113724ab-0028-493f-9605-6e8570f0939f@iki.fi> In-Reply-To: <113724ab-0028-493f-9605-6e8570f0939f@iki.fi> From: Robert Haas Date: Wed, 25 Mar 2026 14:37:18 -0400 X-Gm-Features: AQROBzBOdz2u-xNviAGL0Ktn58d6N586dxKRuzMBbMhkaoySHPAzMYXUA6hvGTw Message-ID: Subject: Re: Better shared data structure management and resizable shared data structures To: Heikki Linnakangas Cc: Ashutosh Bapat , Andres Freund , pgsql-hackers , chaturvedipalak1911@gmail.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Sat, Mar 21, 2026 at 8:14=E2=80=AFPM Heikki Linnakangas wrote: > I see your point too, the options will indeed easily start to split > between constant parts and parts that are set later. Yeah. That definitely seems worth trying to fix. > I don't like the idea of just using the string name as the handle. I > think it will come handy to have a backend-private descriptor or handle > to the shared memory region. But perhaps the "name" and "ptr" should be > regular arguments, for example. If some parameters are passed as > arguments and some in the struct, that also splits things in an awkward > way, though. I agree that having a handle object seems potentially useful. Putting arguments that are required to be constant in the struct and passing other things as arguments or in some other way seems like a good idea. > I wonder if we should set aside a small amount of memory, like 10-20 kB, > in the fixed shmem segment for small structs like that. Currently, such > allocations will usually succeed because we leave some wiggle room, but > the can also be consumed by other things like locks. But we could > reserve a small amount of memory specifically for small allocations in > extensions like this. Yeah, I don't really understand why we let the lock table use up that space. I mean, I think it would be useful to have a way to let the lock table expand without a server restart, and I also suspect that we could come up with a less-silly data structure than the PROCLOCK hash, but also if the only thing keeping you from running out of lock space is the wiggle room, maybe you just need to bump up max_locks_per_transaction. Like, you could easily burn through the wiggle room, get an error anyway, and then later find that you also now can't load certain extensions without a server restart. > Shmem callbacks > --------------- > > I separated the request/init/fn callbacks from the structs. There's now > a concept of "shmem callbacks", which you register in _PG_init(). For > example: > > static void pgss_shmem_request(void *arg); > static void pgss_shmem_init(void *arg); > > static const ShmemCallbacks pgss_shmem_callbacks =3D { > .request_fn =3D pgss_shmem_request, > .init_fn =3D pgss_shmem_init, > .attach_fn =3D NULL, /* no special attach actions needed */ > }; What's the advantage of coupling the functions together this way, vs. just registering each callback individually? Also, I don't understand what "arg" is supposed to be doing. It doesn't seem to be getting used for anything. I wonder if we should think about just adjusting the timing of the existing callbacks instead of adding new things. I mean, maybe that's too likely to cause silent breakage, in which case we could also replace them with new callbacks with slightly different names. But there's something to be said for a hard cutover -- or at least not letting both ways coexist for more than a few releases. > This is a similar to the old shmem_request and shmem_startup hooks. It's > not a one-to-one replacement though, the callbacks are called at > different stages than the old hooks (to make things convenient with the > new facility): > > * The request_fn callback is called in postmaster startup, at the same > stage as the old shmem_request callback was. But in EXEC_BACKEND mode, > it's *also* called in each backend. > > * The init_fn callback is only called in postmaster startup, when it's > time to initialize the area. (Ignoring the special "after startup" > allocations for now). Trying to improve the timing of the callbacks makes sense to me as a concept, without taking a position on these particular choices (and definitely hoping for some after-startup improvements). Looking at v7-0018 (any chance you have a public branch where I can look at this without having to download and apply all the patches one by one?) it seems like this gets rid of the need for a bunch of IsUnderPostmaster checks in individual subsystems, and some if (found)/if (!found) checks, which I definitely like. > Shmem requests > -------------- > > To register a shmem area, you call ShmemRequestStruct() or > ShmmeRequestHash() from the request callback function. For example: > > static void > pgss_shmem_request(void *arg) > { > static ShmemHashDesc pgssSharedHashDesc =3D { > .name =3D "pg_stat_statements hash", > .ptr =3D &pgss_hash, > .hash_info.keysize =3D sizeof(pgssHashKey), > .hash_info.entrysize =3D sizeof(pgssEntry), > .hash_flags =3D HASH_ELEM | HASH_BLOBS, > }; > static ShmemStructDesc pgssSharedStateDesc =3D { > .name =3D "pg_stat_statements", > .size =3D sizeof(pgssSharedState), > .ptr =3D (void **) &pgss, > }; > > pgssSharedHashDesc.init_size =3D pgss_max; > pgssSharedHashDesc.max_size =3D pgss_max; > ShmemRequestHash(&pgssSharedHashDesc); > ShmemRequestStruct(&pgssSharedStateDesc); > } > > Initialization happens in the init callback, which is called after all > the pointers (pgss, pgss_hash) have been set. I think this is not bad. I suppose it lets you get a complete list of all of the descriptors someplace. It seems to avoid double-computing the request size, or any possibility of drift between the requested size and the allocated size. Having to create the struct and then set the size afterward in some cases is a tiny bit awkward-looking, but it's not awful. I do wonder if some coding pattern might creep in where people create the struct and register it and then try to change the size, or other fields, afterward. I'm tempted to propose making the struct non-static and having the registration functions copy it, so that there can be absolutely no question of getting away with such antisocial behavior. --=20 Robert Haas EDB: http://www.enterprisedb.com