Re: Improve heavyweight locks instead of building new lock managers?

From: Andres Freund <andres(at)anarazel(dot)de>
To: Thomas Munro <thomas(dot)munro(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Robert Haas <robertmhaas(at)gmail(dot)com>, Michael Paquier <michael(at)paquier(dot)xyz>, Mithun Cy <mithun(dot)cy(at)enterprisedb(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>, Masahiko Sawada <masahiko(dot)sawada(at)2ndquadrant(dot)com>
Subject: Re: Improve heavyweight locks instead of building new lock managers?
Date: 2020-03-23 22:23:50
Message-ID: 20200323222350.vjc4t36rb34fz4ie@alap3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On 2020-02-21 12:40:06 +1300, Thomas Munro wrote:
> On Thu, Feb 20, 2020 at 5:14 PM Andres Freund <andres(at)anarazel(dot)de> wrote:
> > 16 files changed, 569 insertions(+), 1053 deletions(-)
>
> Nice!

Thanks!

> Some comments on 0001, 0003, 0004:
>
> > Subject: [PATCH v1 1/6] Add additional prev/next & detached node functions to
>
> +extern void dlist_check(const dlist_head *head);
> +extern void slist_check(const slist_head *head);
>
> I approve of the incidental constification in this patch.

It was just necessary fallout :)

> +/*
> + * Like dlist_delete(), but also sets next/prev to NULL to signal not being in
> + * list.
> + */
> +static inline void
> +dlist_delete_thoroughly(dlist_node *node)
> +{
> + node->prev->next = node->next;
> + node->next->prev = node->prev;
> + node->next = NULL;
> + node->prev = NULL;
> +}
>
> Instead of introducing this strange terminology, why not just have the
> callers do ...
>
> dlist_delete(node);
> dlist_node_init(node);

There's quite a few callers in predicate.c - I actually did that first.

> ..., or perhaps supply dlist_delete_and_reinit(node) that does exactly
> that? That is, reuse the code and terminology.

Yea, that's might be better, but see paragraph below. I quite dislike
adding any "empty node" state.

> +/*
> + * Check if node is detached. A node is only detached if it either has been
> + * initialized with dlist_init_node(), or deleted with
> + * dlist_delete_thoroughly().
> + */
> +static inline bool
> +dlist_node_is_detached(const dlist_node *node)
> +{
> + Assert((node->next == NULL && node->prev == NULL) ||
> + (node->next != NULL && node->prev != NULL));
> +
> + return node->next == NULL;
> +}
>
> How about dlist_node_is_linked()? I don't like introducing random new
> verbs when we already have 'linked' in various places, and these
> things are, y'know, linked lists.

Well, but that doesn't signal that you can't just delete and have
dlist_node_is_linked() work. I *want* it to sound "different". We could
of course make delete always do this, but I don't want to add that
overhead unnecessarily.

> > Subject: [PATCH v1 4/6] Use dlists for predicate locking.
>
> + dlist_foreach(iter, &unconstify(SERIALIZABLEXACT *, reader)->outConflicts)
>
> Yuck...

It doesn't seem *that* bad to me, at least signals properly what we're
doing, and only does so in one place.

> I suppose you could do this:
>
> - dlist_foreach(iter, &unconstify(SERIALIZABLEXACT *, reader)->outConflicts)
> + dlist_foreach_const(iter, &reader->outConflicts)

We'd need a different iterator type too, I think? Because the iterator
itself can't be constant, but we'd want the elements themselves be
pointers to constants.

const just isn't a very granular thing in C :(.

> ... given:
>
> +/* Variant for when you have a pointer to const dlist_head. */
> +#define dlist_foreach_const(iter, lhead) \
> + for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \
> + AssertVariableIsOfTypeMacro(lhead, const dlist_head *), \
> + (iter).end = (dlist_node *) &(lhead)->head, \
> + (iter).cur = (iter).end->next ? (iter).end->next : (iter).end; \
> + (iter).cur != (iter).end; \
> + (iter).cur = (iter).cur->next)
> +
>
> ... or find a way to make dlist_foreach() handle that itself, which
> seems pretty reasonable given its remit to traverse lists without
> modifying them, though perhaps that would require a different iterator
> type...

I was trying that first, but I don't easily see how we can do
so. Iterating over a non-constant list with dlist_foreach obviously
still allows to to manipulate the list members. Thus dlist_iter.cur
can't be a 'pointer to const'. Whereas that's arguably what'd be needed
for a correct dlist_foreach() of a constant list?

We could just accept const pointers for dlist_foreach(), but then we'd
*always* accept them, and we'd thus unconditionally have iter.cur as
non-const. Would that be better?

> Otherwise looks OK to me and passes various tests I threw at it

Thanks!

Greetings,

Andres Freund

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2020-03-23 22:38:53 Re: backend type in log_line_prefix?
Previous Message Bruce Momjian 2020-03-23 22:14:56 Re: Internal key management system