On Mon, Oct 05, 2026 at 04:13:37PM -0500, Sami Imseih wrote:
> I kept own_hash tied to a dedicated DSA for now. I am not sure we would want 
> to
> support that mix and match behavior. A stats kind that asks for its own hash 
> is
> already asking to be isolated from the shared stats table, and using a 
> dedicated
> DSA keeps the hash storage and entry storage isolated in the same way.
> 
> I have not thought of a good use case for splitting those controls, but 
> perhaps
> there is one.
> 
> Attached is v2

+       dsa_area   *kind_dsa[PGSTAT_KIND_MAX + 1];
        dshash_table *shared_hash;
+       dshash_table *kind_hash[PGSTAT_KIND_MAX + 1];
[...]
+pgstat_get_hash_for_kind(PgStat_Kind kind)
+{
+       if (pgStatLocal.kind_hash[kind] != NULL)
+               return pgStatLocal.kind_hash[kind];
+
+       Assert(!pgstat_get_kind_info(kind)->own_hash);
+       return pgStatLocal.shared_hash;
+}
[...]
+       /* Attach dedicated DSAs and hash tables */
+       for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; 
kind++)
[...]
+               else
+               {
+                       pgStatLocal.kind_dsa[kind] = NULL;
+                       pgStatLocal.kind_hash[kind] = NULL;
+               }

Having both shared_hash and kind_dsa/kind_hash feels duplicated.  Hmm.
How about enforcing a policy so as kind_dsa/kind_hash are always set
for variable-sized stats kinds?  If kind_hash_valid is true, point
these to the main shared hashtable instead of using NULL.  That would
make pgstat_get_hash_for_kind() unnecessary.  And then perhaps remove
the shared hashtable pointer all together from the main structure?
It looks like the decision-making could just be driven by
kind_hash_valid, for the most parts.

pgstat_get_dsa_for_kind() is a nice wrapper to keep, as that means
less dshash_get_dsa_area() footprint.

+       /* All hash tables to iterate (shared + per-kind), built at attach time 
*/
+       dshash_table *all_hashes[PGSTAT_KIND_MAX + 1];
+       int                     num_hashes;

It looks like you are right to have this optimization with an
additional array.  That speeds the flush of the stats by not having to
go through all PGSTAT_KIND_MAX entries, which I suspect could become
costly with very short queries a-la "SELECT 1".

        /* dshash entry is not modified, take shared lock */
-       dshash_seq_init(&hstat, pgStatLocal.shared_hash, false);
-       while ((p = dshash_seq_next(&hstat)) != NULL)

This code has been moved to pgstat_reset_matching_entries_in_hash(),
and the corresponding comment is gone.  That's important to keep
documented.

        /* entries are removed, take an exclusive lock */
-       dshash_seq_init(&hstat, pgStatLocal.shared_hash, true);
-       while ((ps = dshash_seq_next(&hstat)) != NULL)
+       for (int h = 0; h < pgStatLocal.num_hashes; h++)
        {
-               if (ps->dropped)
-                       continue;
+               dshash_seq_init(&hstat, pgStatLocal.all_hashes[h], true);

Similar remark here.  The exclusive lock part applies to
dshash_seq_init().
--
Michael

Attachment: signature.asc
Description: PGP signature

Reply via email to