mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Improve sift up/down code in binaryheap.c and logtape.c.
Borrow the logic that's long been used in tuplesort.c: instead of physically swapping the data in two heap entries, keep the value that's being sifted up or down in a local variable, and just move the other values as necessary. This makes the code shorter as well as faster. It's not clear that any current callers are really time-critical enough to notice, but we might as well code heap maintenance the same way everywhere. Ma Liangzhu and Tom Lane Discussion: https://postgr.es/m/17336-fc4e522d26a750fd@postgresql.org
This commit is contained in:
@@ -340,16 +340,6 @@ ltsReadFillBuffer(LogicalTape *lt)
|
||||
return (lt->nbytes > 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
swap_nodes(long *heap, unsigned long a, unsigned long b)
|
||||
{
|
||||
long swap;
|
||||
|
||||
swap = heap[a];
|
||||
heap[a] = heap[b];
|
||||
heap[b] = swap;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
left_offset(unsigned long i)
|
||||
{
|
||||
@@ -390,31 +380,33 @@ ltsGetFreeBlock(LogicalTapeSet *lts)
|
||||
long *heap = lts->freeBlocks;
|
||||
long blocknum;
|
||||
int heapsize;
|
||||
unsigned long pos;
|
||||
long holeval;
|
||||
unsigned long holepos;
|
||||
|
||||
/* freelist empty; allocate a new block */
|
||||
if (lts->nFreeBlocks == 0)
|
||||
return lts->nBlocksAllocated++;
|
||||
|
||||
/* easy if heap contains one element */
|
||||
if (lts->nFreeBlocks == 1)
|
||||
{
|
||||
lts->nFreeBlocks--;
|
||||
return lts->freeBlocks[0];
|
||||
}
|
||||
|
||||
/* take top of minheap */
|
||||
/* remove top of minheap */
|
||||
blocknum = heap[0];
|
||||
|
||||
/* replace with end of minheap array */
|
||||
heap[0] = heap[--lts->nFreeBlocks];
|
||||
/* we'll replace it with end of minheap array */
|
||||
holeval = heap[--lts->nFreeBlocks];
|
||||
|
||||
/* sift down */
|
||||
pos = 0;
|
||||
holepos = 0; /* holepos is where the "hole" is */
|
||||
heapsize = lts->nFreeBlocks;
|
||||
while (true)
|
||||
{
|
||||
unsigned long left = left_offset(pos);
|
||||
unsigned long right = right_offset(pos);
|
||||
unsigned long left = left_offset(holepos);
|
||||
unsigned long right = right_offset(holepos);
|
||||
unsigned long min_child;
|
||||
|
||||
if (left < heapsize && right < heapsize)
|
||||
@@ -426,12 +418,13 @@ ltsGetFreeBlock(LogicalTapeSet *lts)
|
||||
else
|
||||
break;
|
||||
|
||||
if (heap[min_child] >= heap[pos])
|
||||
if (heap[min_child] >= holeval)
|
||||
break;
|
||||
|
||||
swap_nodes(heap, min_child, pos);
|
||||
pos = min_child;
|
||||
heap[holepos] = heap[min_child];
|
||||
holepos = min_child;
|
||||
}
|
||||
heap[holepos] = holeval;
|
||||
|
||||
return blocknum;
|
||||
}
|
||||
@@ -483,7 +476,7 @@ static void
|
||||
ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
|
||||
{
|
||||
long *heap;
|
||||
unsigned long pos;
|
||||
unsigned long holepos;
|
||||
|
||||
/*
|
||||
* Do nothing if we're no longer interested in remembering free space.
|
||||
@@ -508,24 +501,23 @@ ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
|
||||
lts->freeBlocksLen * sizeof(long));
|
||||
}
|
||||
|
||||
/* create a "hole" at end of minheap array */
|
||||
heap = lts->freeBlocks;
|
||||
pos = lts->nFreeBlocks;
|
||||
|
||||
/* place entry at end of minheap array */
|
||||
heap[pos] = blocknum;
|
||||
holepos = lts->nFreeBlocks;
|
||||
lts->nFreeBlocks++;
|
||||
|
||||
/* sift up */
|
||||
while (pos != 0)
|
||||
/* sift up to insert blocknum */
|
||||
while (holepos != 0)
|
||||
{
|
||||
unsigned long parent = parent_offset(pos);
|
||||
unsigned long parent = parent_offset(holepos);
|
||||
|
||||
if (heap[parent] < heap[pos])
|
||||
if (heap[parent] < blocknum)
|
||||
break;
|
||||
|
||||
swap_nodes(heap, parent, pos);
|
||||
pos = parent;
|
||||
heap[holepos] = heap[parent];
|
||||
holepos = parent;
|
||||
}
|
||||
heap[holepos] = blocknum;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user