From 185b4272844970a9e1b46eb3d1d16d4e5ecca939 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Mon, 31 May 1999 23:48:04 +0000 Subject: [PATCH] Fix some latent bugs in dllist.c (carelessness about setting all fields that should be set). Add a MoveToFront primitive to speed up one of the hotspots in SearchSysCache. --- src/backend/lib/dllist.c | 96 ++++++++++++++++++++---------- src/backend/utils/cache/catcache.c | 14 +++-- src/include/lib/dllist.h | 3 +- 3 files changed, 73 insertions(+), 40 deletions(-) diff --git a/src/backend/lib/dllist.c b/src/backend/lib/dllist.c index 9aeb82f266c..3ca7cf03c74 100644 --- a/src/backend/lib/dllist.c +++ b/src/backend/lib/dllist.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.12 1999/02/13 23:15:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.13 1999/05/31 23:48:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,9 @@ DLNewList(void) return l; } - /* free up a list and all the nodes in it */ +/* free up a list and all the nodes in it --- but *not* whatever the nodes + * might point to! + */ void DLFreeList(Dllist *l) { @@ -85,7 +87,7 @@ DLGetTail(Dllist *l) return l ? l->dll_tail : 0; } -/* get the value stored in the first element */ +/* get the value stored in the last element */ #ifdef NOT_USED void * DLGetTailVal(Dllist *l) @@ -112,20 +114,26 @@ DLGetSucc(Dlelem *e) /* get successor */ void DLRemove(Dlelem *e) { - Dllist *l; + Dllist *l = e->dle_list; if (e->dle_prev) e->dle_prev->dle_next = e->dle_next; + else /* must be the head element */ + { + Assert(e == l->dll_head); + l->dll_head = e->dle_next; + } if (e->dle_next) e->dle_next->dle_prev = e->dle_prev; + else /* must be the tail element */ + { + Assert(e == l->dll_tail); + l->dll_tail = e->dle_prev; + } - /* check to see if we're removing the head or tail */ - l = e->dle_list; - if (e == l->dll_head) - DLRemHead(l); - if (e == l->dll_tail) - DLRemTail(l); - + e->dle_next = 0; + e->dle_prev = 0; + e->dle_list = 0; } void @@ -134,15 +142,13 @@ DLAddHead(Dllist *l, Dlelem *e) e->dle_list = l; if (l->dll_head) - { l->dll_head->dle_prev = e; - e->dle_next = l->dll_head; - } + e->dle_next = l->dll_head; e->dle_prev = 0; l->dll_head = e; if (l->dll_tail == 0) /* if this is first element added */ - l->dll_tail = l->dll_head; + l->dll_tail = e; } void @@ -151,31 +157,28 @@ DLAddTail(Dllist *l, Dlelem *e) e->dle_list = l; if (l->dll_tail) - { l->dll_tail->dle_next = e; - e->dle_prev = l->dll_tail; - } + e->dle_prev = l->dll_tail; e->dle_next = 0; l->dll_tail = e; if (l->dll_head == 0) /* if this is first element added */ - l->dll_head = l->dll_tail; + l->dll_head = e; } Dlelem * DLRemHead(Dllist *l) { /* remove and return the head */ - Dlelem *result; + Dlelem *result = l->dll_head; - if (l->dll_head == 0) - return 0; + if (result == 0) + return result; - result = l->dll_head; - if (l->dll_head->dle_next) - l->dll_head->dle_next->dle_prev = 0; + if (result->dle_next) + result->dle_next->dle_prev = 0; - l->dll_head = l->dll_head->dle_next; + l->dll_head = result->dle_next; result->dle_next = 0; result->dle_list = 0; @@ -190,15 +193,15 @@ Dlelem * DLRemTail(Dllist *l) { /* remove and return the tail */ - Dlelem *result; + Dlelem *result = l->dll_tail; - if (l->dll_tail == 0) - return 0; + if (result == 0) + return result; - result = l->dll_tail; - if (l->dll_tail->dle_prev) - l->dll_tail->dle_prev->dle_next = 0; - l->dll_tail = l->dll_tail->dle_prev; + if (result->dle_prev) + result->dle_prev->dle_next = 0; + + l->dll_tail = result->dle_prev; result->dle_prev = 0; result->dle_list = 0; @@ -208,3 +211,30 @@ DLRemTail(Dllist *l) return result; } + +/* Same as DLRemove followed by DLAddHead, but faster */ +void +DLMoveToFront(Dlelem *e) +{ + Dllist *l = e->dle_list; + + if (l->dll_head == e) + return; /* Fast path if already at front */ + + Assert(e->dle_prev != 0); /* since it's not the head */ + e->dle_prev->dle_next = e->dle_next; + + if (e->dle_next) + e->dle_next->dle_prev = e->dle_prev; + else /* must be the tail element */ + { + Assert(e == l->dll_tail); + l->dll_tail = e->dle_prev; + } + + l->dll_head->dle_prev = e; + e->dle_next = l->dll_head; + e->dle_prev = 0; + l->dll_head = e; + /* We need not check dll_tail, since there must have been > 1 entry */ +} diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 80444d0a143..cc76acdd747 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.41 1999/05/25 16:12:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.42 1999/05/31 23:48:04 tgl Exp $ * * Notes: * XXX This needs to use exception.h to handle recovery when @@ -876,16 +876,18 @@ SearchSysCache(struct catcache * cache, /* ---------------- * if we found a tuple in the cache, move it to the top of the - * lru list, and return it. + * lru list, and return it. We also move it to the front of the + * list for its hashbucket, in order to speed subsequent searches. + * (The most frequently accessed elements in any hashbucket will + * tend to be near the front of the hashbucket's list.) * ---------------- */ if (elt) { - Dlelem *old_lru_elt; + Dlelem *old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node; - old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node; - DLRemove(old_lru_elt); - DLAddHead(cache->cc_lrulist, old_lru_elt); + DLMoveToFront(old_lru_elt); + DLMoveToFront(elt); #ifdef CACHEDEBUG relation = heap_open(cache->relationId); diff --git a/src/include/lib/dllist.h b/src/include/lib/dllist.h index 7c3707afcab..a367450185c 100644 --- a/src/include/lib/dllist.h +++ b/src/include/lib/dllist.h @@ -26,7 +26,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: dllist.h,v 1.9 1999/02/13 23:21:30 momjian Exp $ + * $Id: dllist.h,v 1.10 1999/05/31 23:48:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -66,6 +66,7 @@ extern void DLRemove(Dlelem *); /* removes node from list */ extern void DLAddHead(Dllist *list, Dlelem *node); extern void DLAddTail(Dllist *list, Dlelem *node); extern Dlelem *DLRemHead(Dllist *list); /* remove and return the head */ +extern void DLMoveToFront(Dlelem *); /* move node to front of its list */ #define DLE_VAL(x) (x->dle_val) -- GitLab