Commit 1b88b890 authored by Thomas Munro's avatar Thomas Munro

Specialize checkpointer sort functions.

When sorting a potentially large number of dirty buffers, the
checkpointer can benefit from a faster sort routine.  One reported
improvement on a large buffer pool system was 1.4s -> 0.6s.
Reviewed-by: default avatarAndres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA%2BhUKGJ2-eaDqAum5bxhpMNhvuJmRDZxB_Tow0n-gse%2BHG0Yig%40mail.gmail.com
parent 519e4c9e
...@@ -488,8 +488,8 @@ static void FindAndDropRelFileNodeBuffers(RelFileNode rnode, ...@@ -488,8 +488,8 @@ static void FindAndDropRelFileNodeBuffers(RelFileNode rnode,
static void AtProcExit_Buffers(int code, Datum arg); static void AtProcExit_Buffers(int code, Datum arg);
static void CheckForBufferLeaks(void); static void CheckForBufferLeaks(void);
static int rnode_comparator(const void *p1, const void *p2); static int rnode_comparator(const void *p1, const void *p2);
static int buffertag_comparator(const void *p1, const void *p2); static inline int buffertag_comparator(const BufferTag *a, const BufferTag *b);
static int ckpt_buforder_comparator(const void *pa, const void *pb); static inline int ckpt_buforder_comparator(const CkptSortItem *a, const CkptSortItem *b);
static int ts_ckpt_progress_comparator(Datum a, Datum b, void *arg); static int ts_ckpt_progress_comparator(Datum a, Datum b, void *arg);
...@@ -1831,6 +1831,13 @@ UnpinBuffer(BufferDesc *buf, bool fixOwner) ...@@ -1831,6 +1831,13 @@ UnpinBuffer(BufferDesc *buf, bool fixOwner)
} }
} }
#define ST_SORT sort_checkpoint_bufferids
#define ST_ELEMENT_TYPE CkptSortItem
#define ST_COMPARE(a, b) ckpt_buforder_comparator(a, b)
#define ST_SCOPE static
#define ST_DEFINE
#include <lib/sort_template.h>
/* /*
* BufferSync -- Write out all dirty buffers in the pool. * BufferSync -- Write out all dirty buffers in the pool.
* *
...@@ -1931,8 +1938,7 @@ BufferSync(int flags) ...@@ -1931,8 +1938,7 @@ BufferSync(int flags)
* end up writing to the tablespaces one-by-one; possibly overloading the * end up writing to the tablespaces one-by-one; possibly overloading the
* underlying system. * underlying system.
*/ */
qsort(CkptBufferIds, num_to_scan, sizeof(CkptSortItem), sort_checkpoint_bufferids(CkptBufferIds, num_to_scan);
ckpt_buforder_comparator);
num_spaces = 0; num_spaces = 0;
...@@ -4567,11 +4573,9 @@ WaitBufHdrUnlocked(BufferDesc *buf) ...@@ -4567,11 +4573,9 @@ WaitBufHdrUnlocked(BufferDesc *buf)
/* /*
* BufferTag comparator. * BufferTag comparator.
*/ */
static int static inline int
buffertag_comparator(const void *a, const void *b) buffertag_comparator(const BufferTag *ba, const BufferTag *bb)
{ {
const BufferTag *ba = (const BufferTag *) a;
const BufferTag *bb = (const BufferTag *) b;
int ret; int ret;
ret = rnode_comparator(&ba->rnode, &bb->rnode); ret = rnode_comparator(&ba->rnode, &bb->rnode);
...@@ -4598,12 +4602,9 @@ buffertag_comparator(const void *a, const void *b) ...@@ -4598,12 +4602,9 @@ buffertag_comparator(const void *a, const void *b)
* It is important that tablespaces are compared first, the logic balancing * It is important that tablespaces are compared first, the logic balancing
* writes between tablespaces relies on it. * writes between tablespaces relies on it.
*/ */
static int static inline int
ckpt_buforder_comparator(const void *pa, const void *pb) ckpt_buforder_comparator(const CkptSortItem *a, const CkptSortItem *b)
{ {
const CkptSortItem *a = (const CkptSortItem *) pa;
const CkptSortItem *b = (const CkptSortItem *) pb;
/* compare tablespace */ /* compare tablespace */
if (a->tsId < b->tsId) if (a->tsId < b->tsId)
return -1; return -1;
...@@ -4694,6 +4695,13 @@ ScheduleBufferTagForWriteback(WritebackContext *context, BufferTag *tag) ...@@ -4694,6 +4695,13 @@ ScheduleBufferTagForWriteback(WritebackContext *context, BufferTag *tag)
IssuePendingWritebacks(context); IssuePendingWritebacks(context);
} }
#define ST_SORT sort_pending_writebacks
#define ST_ELEMENT_TYPE PendingWriteback
#define ST_COMPARE(a, b) buffertag_comparator(&a->tag, &b->tag)
#define ST_SCOPE static
#define ST_DEFINE
#include <lib/sort_template.h>
/* /*
* Issue all pending writeback requests, previously scheduled with * Issue all pending writeback requests, previously scheduled with
* ScheduleBufferTagForWriteback, to the OS. * ScheduleBufferTagForWriteback, to the OS.
...@@ -4713,8 +4721,7 @@ IssuePendingWritebacks(WritebackContext *context) ...@@ -4713,8 +4721,7 @@ IssuePendingWritebacks(WritebackContext *context)
* Executing the writes in-order can make them a lot faster, and allows to * Executing the writes in-order can make them a lot faster, and allows to
* merge writeback requests to consecutive blocks into larger writebacks. * merge writeback requests to consecutive blocks into larger writebacks.
*/ */
qsort(&context->pending_writebacks, context->nr_pending, sort_pending_writebacks(context->pending_writebacks, context->nr_pending);
sizeof(PendingWriteback), buffertag_comparator);
/* /*
* Coalesce neighbouring writes, but nothing else. For that we iterate * Coalesce neighbouring writes, but nothing else. For that we iterate
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment