From 72a25761300d02af1aea4f21cc05170531da0b08 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Wed, 27 Jun 2018 11:18:01 +1200 Subject: [PATCH] Use a doubly-linked list for unowned relations. Previously we used a singly-linked list, which required remove_from_unowned_list() to perform an O(n) search. Make it O(1). Author: Thomas Munro Discussion: https://postgr.es/m/CAHGQGwHVQkdfDqtvGVkty+19cQakAydXn1etGND3X0PHbZ3+6w@mail.gmail.com --- src/backend/storage/smgr/smgr.c | 43 ++++++++++++++++----------------- src/include/storage/smgr.h | 1 + 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index 08f06bade25..ae6da4928fc 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -236,15 +236,15 @@ smgrclearowner(SMgrRelation *owner, SMgrRelation reln) /* * add_to_unowned_list -- link an SMgrRelation onto the unowned list - * - * Check remove_from_unowned_list()'s comments for performance - * considerations. */ static void add_to_unowned_list(SMgrRelation reln) { - /* place it at head of the list (to make smgrsetowner cheap) */ + /* place it at head of the list */ + reln->prev_unowned_reln = NULL; reln->next_unowned_reln = first_unowned_reln; + if (first_unowned_reln) + first_unowned_reln->prev_unowned_reln = reln; first_unowned_reln = reln; } @@ -253,30 +253,29 @@ add_to_unowned_list(SMgrRelation reln) * * If the reln is not present in the list, nothing happens. Typically this * would be caller error, but there seems no reason to throw an error. - * - * In the worst case this could be rather slow; but in all the cases that seem - * likely to be performance-critical, the reln being sought will actually be - * first in the list. Furthermore, the number of unowned relns touched in any - * one transaction shouldn't be all that high typically. So it doesn't seem - * worth expending the additional space and management logic needed for a - * doubly-linked list. */ static void remove_from_unowned_list(SMgrRelation reln) { - SMgrRelation *link; - SMgrRelation cur; + SMgrRelation prev = reln->prev_unowned_reln; + SMgrRelation next = reln->next_unowned_reln; - for (link = &first_unowned_reln, cur = *link; - cur != NULL; - link = &cur->next_unowned_reln, cur = *link) + if (first_unowned_reln == reln) + { + /* It is at the head of the list. */ + Assert(prev == NULL); + first_unowned_reln = next; + if (next) + next->prev_unowned_reln = NULL; + reln->next_unowned_reln = NULL; + } + else if (prev != NULL) { - if (cur == reln) - { - *link = cur->next_unowned_reln; - cur->next_unowned_reln = NULL; - break; - } + /* It is in the list, but not at the head. */ + prev->next_unowned_reln = next; + if (next) + next->prev_unowned_reln = prev; + reln->next_unowned_reln = reln->prev_unowned_reln = NULL; } } diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index 558e4d8518b..1bd978a7351 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -72,6 +72,7 @@ typedef struct SMgrRelationData struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1]; /* if unowned, list link in list of all unowned SMgrRelations */ + struct SMgrRelationData *prev_unowned_reln; struct SMgrRelationData *next_unowned_reln; } SMgrRelationData; -- 2.17.0