v6-0002-Optimize-setitimer-usage.patch
application/octet-stream
Filename: v6-0002-Optimize-setitimer-usage.patch
Type: application/octet-stream
Part: 1
Message:
Re: Terminate the idle sessions
Patch
Format: format-patch
Series: patch v6-0002
Subject: Optimize setitimer() usage.
| File | + | − |
|---|---|---|
| src/backend/utils/misc/timeout.c | 24 | 18 |
From 58ab9d8e674366e61c3427ce7c58c3ac26e850cb Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sun, 30 Aug 2020 23:22:19 +1200
Subject: [PATCH v6 2/2] Optimize setitimer() usage.
Don't call setitimer() so often. Instead, let a preexisting alarm expire
and then request a new one as requried. It's better to take a few extra
spurious alarm interrupts at a rate that's a function of the timeout
setting than to have a system call rate that's a function of statement
execution frequency.
XXX: Need to review this carefully for races, perhaps involving
reentrancy.
---
src/backend/utils/misc/timeout.c | 42 ++++++++++++++++++--------------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/src/backend/utils/misc/timeout.c b/src/backend/utils/misc/timeout.c
index f1c9518b0c..b5027815db 100644
--- a/src/backend/utils/misc/timeout.c
+++ b/src/backend/utils/misc/timeout.c
@@ -51,6 +51,13 @@ static bool all_timeouts_initialized = false;
static volatile int num_active_timeouts = 0;
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS];
+/*
+ * State used to avoid installing a new timer interrupt when the previous one
+ * hasn't fired yet, but isn't too late.
+ */
+static TimestampTz sigalrm_due_at = PG_INT64_MAX;
+static volatile sig_atomic_t sigalrm_delivered = false;
+
/*
* Flag controlling whether the signal handler is allowed to do anything.
* We leave this "false" when we're not expecting interrupts, just in case.
@@ -195,12 +202,13 @@ schedule_alarm(TimestampTz now)
struct itimerval timeval;
long secs;
int usecs;
+ TimestampTz nearest_timeout;
MemSet(&timeval, 0, sizeof(struct itimerval));
/* Get the time remaining till the nearest pending timeout */
- TimestampDifference(now, active_timeouts[0]->fin_time,
- &secs, &usecs);
+ nearest_timeout = active_timeouts[0]->fin_time;
+ TimestampDifference(now, nearest_timeout, &secs, &usecs);
/*
* It's possible that the difference is less than a microsecond;
@@ -244,9 +252,18 @@ schedule_alarm(TimestampTz now)
*/
enable_alarm();
+ /*
+ * Try to avoid having to set the interval timer, if we already know
+ * that there is an undelivered signal due at the same time or sooner.
+ */
+ if (nearest_timeout >= sigalrm_due_at && !sigalrm_delivered)
+ return;
+
/* Set the alarm timer */
if (setitimer(ITIMER_REAL, &timeval, NULL) != 0)
elog(FATAL, "could not enable SIGALRM timer: %m");
+ sigalrm_due_at = nearest_timeout;
+ sigalrm_delivered = false;
}
}
@@ -266,6 +283,8 @@ handle_sig_alarm(SIGNAL_ARGS)
{
int save_errno = errno;
+ sigalrm_delivered = true;
+
/*
* Bump the holdoff counter, to make sure nothing we call will process
* interrupts directly. No timeout handler should do that, but these
@@ -591,8 +610,9 @@ disable_timeouts(const DisableTimeoutParams *timeouts, int count)
}
/*
- * Disable SIGALRM and remove all timeouts from the active list,
- * and optionally reset their timeout indicators.
+ * Remove all timeouts from the active list, and optionally reset their timeout
+ * indicators. Leave any existing itimer installed, because it may allow us to
+ * avoid having to set it again soon.
*/
void
disable_all_timeouts(bool keep_indicators)
@@ -601,20 +621,6 @@ disable_all_timeouts(bool keep_indicators)
disable_alarm();
- /*
- * Only bother to reset the timer if we think it's active. We could just
- * let the interrupt happen anyway, but it's probably a bit cheaper to do
- * setitimer() than to let the useless interrupt happen.
- */
- if (num_active_timeouts > 0)
- {
- struct itimerval timeval;
-
- MemSet(&timeval, 0, sizeof(struct itimerval));
- if (setitimer(ITIMER_REAL, &timeval, NULL) != 0)
- elog(FATAL, "could not disable SIGALRM timer: %m");
- }
-
num_active_timeouts = 0;
for (i = 0; i < MAX_TIMEOUTS; i++)
--
2.28.0