Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit171c457

Browse files
committed
Fix and simplify some usages of TimestampDifference().
Introduce TimestampDifferenceMilliseconds() to simplify callersthat would rather have the difference in milliseconds, instead ofthe select()-oriented seconds-and-microseconds format. This getsrid of at least one integer division per call, and it eliminatessome apparently-easy-to-mess-up arithmetic.Two of these call sites were in fact wrong:* pg_prewarm's autoprewarm_main() forgot to multiply the secondsby 1000, thus ending up with a delay 1000X shorter than intended.That doesn't quite make it a busy-wait, but close.* postgres_fdw's pgfdw_get_cleanup_result() thought it needed to computemicroseconds not milliseconds, thus ending up with a delay 1000X longerthan intended. Somebody along the way had noticed this problem butmisdiagnosed the cause, and imposed an ad-hoc 60-second limit ratherthan fixing the units. This was relatively harmless in context, becausewe don't care that much about exactly how long this delay is; still,it's wrong.There are a few more callers of TimestampDifference() that don'thave a direct need for seconds-and-microseconds, but can't useTimestampDifferenceMilliseconds() either because they do needmicrosecond precision or because they might possibly deal withintervals long enough to overflow 32-bit milliseconds. It might beworth inventing another API to improve that, but that seems outsidethe scope of this patch; so those callers are untouched here.Given the fact that we are fixing some bugs, and the likelihoodthat future patches might want to back-patch code that uses thisnew API, back-patch to all supported branches.Alexey Kondratov and Tom LaneDiscussion:https://postgr.es/m/3b1c053a21c07c1ed5e00be3b2b855ef@postgrespro.ru
1 parent1393acb commit171c457

File tree

7 files changed

+81
-97
lines changed

7 files changed

+81
-97
lines changed

‎contrib/pg_prewarm/autoprewarm.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,18 +224,16 @@ autoprewarm_main(Datum main_arg)
224224
}
225225
else
226226
{
227-
longdelay_in_ms=0;
228-
TimestampTznext_dump_time=0;
229-
longsecs=0;
230-
intusecs=0;
227+
TimestampTznext_dump_time;
228+
longdelay_in_ms;
231229

232230
/* Compute the next dump time. */
233231
next_dump_time=
234232
TimestampTzPlusMilliseconds(last_dump_time,
235233
autoprewarm_interval*1000);
236-
TimestampDifference(GetCurrentTimestamp(),next_dump_time,
237-
&secs,&usecs);
238-
delay_in_ms=secs+ (usecs /1000);
234+
delay_in_ms=
235+
TimestampDifferenceMilliseconds(GetCurrentTimestamp(),
236+
next_dump_time);
239237

240238
/* Perform a dump if it's time. */
241239
if (delay_in_ms <=0)

‎contrib/postgres_fdw/connection.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,20 +1140,15 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result)
11401140
{
11411141
intwc;
11421142
TimestampTznow=GetCurrentTimestamp();
1143-
longsecs;
1144-
intmicrosecs;
11451143
longcur_timeout;
11461144

11471145
/* If timeout has expired, give up, else get sleep time. */
1148-
if (now >=endtime)
1146+
cur_timeout=TimestampDifferenceMilliseconds(now,endtime);
1147+
if (cur_timeout <=0)
11491148
{
11501149
timed_out= true;
11511150
gotoexit;
11521151
}
1153-
TimestampDifference(now,endtime,&secs,&microsecs);
1154-
1155-
/* To protect against clock skew, limit sleep to one minute. */
1156-
cur_timeout=Min(60000,secs*USECS_PER_SEC+microsecs);
11571152

11581153
/* Sleep until there's something to do */
11591154
wc=WaitLatchOrSocket(MyLatch,

‎src/backend/access/transam/xlog.c

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6005,8 +6005,7 @@ recoveryApplyDelay(XLogReaderState *record)
60056005
{
60066006
uint8xact_info;
60076007
TimestampTzxtime;
6008-
longsecs;
6009-
intmicrosecs;
6008+
longmsecs;
60106009

60116010
/* nothing to do if no delay configured */
60126011
if (recovery_min_apply_delay <=0)
@@ -6047,9 +6046,9 @@ recoveryApplyDelay(XLogReaderState *record)
60476046
* Exit without arming the latch if it's already past time to apply this
60486047
* record
60496048
*/
6050-
TimestampDifference(GetCurrentTimestamp(),recoveryDelayUntilTime,
6051-
&secs,&microsecs);
6052-
if (secs <=0&&microsecs <=0)
6049+
msecs=TimestampDifferenceMilliseconds(GetCurrentTimestamp(),
6050+
recoveryDelayUntilTime);
6051+
if (msecs <=0)
60536052
return false;
60546053

60556054
while (true)
@@ -6066,19 +6065,17 @@ recoveryApplyDelay(XLogReaderState *record)
60666065
* Wait for difference between GetCurrentTimestamp() and
60676066
* recoveryDelayUntilTime
60686067
*/
6069-
TimestampDifference(GetCurrentTimestamp(),recoveryDelayUntilTime,
6070-
&secs,&microsecs);
6068+
msecs=TimestampDifferenceMilliseconds(GetCurrentTimestamp(),
6069+
recoveryDelayUntilTime);
60716070

6072-
/* NB: We're ignoring waits below min_apply_delay's resolution. */
6073-
if (secs <=0&&microsecs /1000 <=0)
6071+
if (msecs <=0)
60746072
break;
60756073

6076-
elog(DEBUG2,"recovery apply delay %ld seconds, %d milliseconds",
6077-
secs,microsecs /1000);
6074+
elog(DEBUG2,"recovery apply delay %ld milliseconds",msecs);
60786075

60796076
(void)WaitLatch(&XLogCtl->recoveryWakeupLatch,
60806077
WL_LATCH_SET |WL_TIMEOUT |WL_EXIT_ON_PM_DEATH,
6081-
secs*1000L+microsecs /1000,
6078+
msecs,
60826079
WAIT_EVENT_RECOVERY_APPLY_DELAY);
60836080
}
60846081
return true;
@@ -8448,33 +8445,24 @@ LogCheckpointStart(int flags, bool restartpoint)
84488445
staticvoid
84498446
LogCheckpointEnd(boolrestartpoint)
84508447
{
8451-
longwrite_secs,
8452-
sync_secs,
8453-
total_secs,
8454-
longest_secs,
8455-
average_secs;
8456-
intwrite_usecs,
8457-
sync_usecs,
8458-
total_usecs,
8459-
longest_usecs,
8460-
average_usecs;
8448+
longwrite_msecs,
8449+
sync_msecs,
8450+
total_msecs,
8451+
longest_msecs,
8452+
average_msecs;
84618453
uint64average_sync_time;
84628454

84638455
CheckpointStats.ckpt_end_t=GetCurrentTimestamp();
84648456

8465-
TimestampDifference(CheckpointStats.ckpt_write_t,
8466-
CheckpointStats.ckpt_sync_t,
8467-
&write_secs,&write_usecs);
8457+
write_msecs=TimestampDifferenceMilliseconds(CheckpointStats.ckpt_write_t,
8458+
CheckpointStats.ckpt_sync_t);
84688459

8469-
TimestampDifference(CheckpointStats.ckpt_sync_t,
8470-
CheckpointStats.ckpt_sync_end_t,
8471-
&sync_secs,&sync_usecs);
8460+
sync_msecs=TimestampDifferenceMilliseconds(CheckpointStats.ckpt_sync_t,
8461+
CheckpointStats.ckpt_sync_end_t);
84728462

84738463
/* Accumulate checkpoint timing summary data, in milliseconds. */
8474-
BgWriterStats.m_checkpoint_write_time+=
8475-
write_secs*1000+write_usecs /1000;
8476-
BgWriterStats.m_checkpoint_sync_time+=
8477-
sync_secs*1000+sync_usecs /1000;
8464+
BgWriterStats.m_checkpoint_write_time+=write_msecs;
8465+
BgWriterStats.m_checkpoint_sync_time+=sync_msecs;
84788466

84798467
/*
84808468
* All of the published timing statistics are accounted for. Only
@@ -8483,25 +8471,20 @@ LogCheckpointEnd(bool restartpoint)
84838471
if (!log_checkpoints)
84848472
return;
84858473

8486-
TimestampDifference(CheckpointStats.ckpt_start_t,
8487-
CheckpointStats.ckpt_end_t,
8488-
&total_secs,&total_usecs);
8474+
total_msecs=TimestampDifferenceMilliseconds(CheckpointStats.ckpt_start_t,
8475+
CheckpointStats.ckpt_end_t);
84898476

84908477
/*
84918478
* Timing values returned from CheckpointStats are in microseconds.
8492-
* Convert to the second plus microsecond form that TimestampDifference
8493-
* returns for homogeneous printing.
8479+
* Convert to milliseconds for consistent printing.
84948480
*/
8495-
longest_secs= (long) (CheckpointStats.ckpt_longest_sync /1000000);
8496-
longest_usecs=CheckpointStats.ckpt_longest_sync-
8497-
(uint64)longest_secs*1000000;
8481+
longest_msecs= (long) ((CheckpointStats.ckpt_longest_sync+999) /1000);
84988482

84998483
average_sync_time=0;
85008484
if (CheckpointStats.ckpt_sync_rels>0)
85018485
average_sync_time=CheckpointStats.ckpt_agg_sync_time /
85028486
CheckpointStats.ckpt_sync_rels;
8503-
average_secs= (long) (average_sync_time /1000000);
8504-
average_usecs=average_sync_time- (uint64)average_secs*1000000;
8487+
average_msecs= (long) ((average_sync_time+999) /1000);
85058488

85068489
elog(LOG,"%s complete: wrote %d buffers (%.1f%%); "
85078490
"%d WAL file(s) added, %d removed, %d recycled; "
@@ -8514,12 +8497,12 @@ LogCheckpointEnd(bool restartpoint)
85148497
CheckpointStats.ckpt_segs_added,
85158498
CheckpointStats.ckpt_segs_removed,
85168499
CheckpointStats.ckpt_segs_recycled,
8517-
write_secs,write_usecs /1000,
8518-
sync_secs,sync_usecs /1000,
8519-
total_secs,total_usecs /1000,
8500+
write_msecs /1000, (int) (write_msecs %1000),
8501+
sync_msecs /1000, (int) (sync_msecs %1000),
8502+
total_msecs /1000, (int) (total_msecs %1000),
85208503
CheckpointStats.ckpt_sync_rels,
8521-
longest_secs,longest_usecs /1000,
8522-
average_secs,average_usecs /1000,
8504+
longest_msecs /1000, (int) (longest_msecs %1000),
8505+
average_msecs /1000, (int) (average_msecs %1000),
85238506
(int) (PrevCheckPointDistance /1024.0),
85248507
(int) (CheckPointDistanceEstimate /1024.0));
85258508
}
@@ -12024,13 +12007,10 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
1202412007
if (!TimestampDifferenceExceeds(last_fail_time,now,
1202512008
wal_retrieve_retry_interval))
1202612009
{
12027-
longsecs,
12028-
wait_time;
12029-
intusecs;
12010+
longwait_time;
1203012011

12031-
TimestampDifference(last_fail_time,now,&secs,&usecs);
1203212012
wait_time=wal_retrieve_retry_interval-
12033-
(secs*1000+usecs /1000);
12013+
TimestampDifferenceMilliseconds(last_fail_time,now);
1203412014

1203512015
(void)WaitLatch(&XLogCtl->recoveryWakeupLatch,
1203612016
WL_LATCH_SET |WL_TIMEOUT |

‎src/backend/replication/walreceiverfuncs.c

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,6 @@ GetReplicationApplyDelay(void)
320320
WalRcvData*walrcv=WalRcv;
321321
XLogRecPtrreceivePtr;
322322
XLogRecPtrreplayPtr;
323-
324-
longsecs;
325-
intusecs;
326-
327323
TimestampTzchunkReplayStartTime;
328324

329325
SpinLockAcquire(&walrcv->mutex);
@@ -340,11 +336,8 @@ GetReplicationApplyDelay(void)
340336
if (chunkReplayStartTime==0)
341337
return-1;
342338

343-
TimestampDifference(chunkReplayStartTime,
344-
GetCurrentTimestamp(),
345-
&secs,&usecs);
346-
347-
return (((int)secs*1000)+ (usecs /1000));
339+
returnTimestampDifferenceMilliseconds(chunkReplayStartTime,
340+
GetCurrentTimestamp());
348341
}
349342

350343
/*
@@ -355,24 +348,14 @@ int
355348
GetReplicationTransferLatency(void)
356349
{
357350
WalRcvData*walrcv=WalRcv;
358-
359351
TimestampTzlastMsgSendTime;
360352
TimestampTzlastMsgReceiptTime;
361353

362-
longsecs=0;
363-
intusecs=0;
364-
intms;
365-
366354
SpinLockAcquire(&walrcv->mutex);
367355
lastMsgSendTime=walrcv->lastMsgSendTime;
368356
lastMsgReceiptTime=walrcv->lastMsgReceiptTime;
369357
SpinLockRelease(&walrcv->mutex);
370358

371-
TimestampDifference(lastMsgSendTime,
372-
lastMsgReceiptTime,
373-
&secs,&usecs);
374-
375-
ms= ((int)secs*1000)+ (usecs /1000);
376-
377-
returnms;
359+
returnTimestampDifferenceMilliseconds(lastMsgSendTime,
360+
lastMsgReceiptTime);
378361
}

‎src/backend/replication/walsender.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,8 +2079,6 @@ WalSndComputeSleeptime(TimestampTz now)
20792079
if (wal_sender_timeout>0&&last_reply_timestamp>0)
20802080
{
20812081
TimestampTzwakeup_time;
2082-
longsec_to_timeout;
2083-
intmicrosec_to_timeout;
20842082

20852083
/*
20862084
* At the latest stop sleeping once wal_sender_timeout has been
@@ -2099,11 +2097,7 @@ WalSndComputeSleeptime(TimestampTz now)
20992097
wal_sender_timeout /2);
21002098

21012099
/* Compute relative time until wakeup. */
2102-
TimestampDifference(now,wakeup_time,
2103-
&sec_to_timeout,&microsec_to_timeout);
2104-
2105-
sleeptime=sec_to_timeout*1000+
2106-
microsec_to_timeout /1000;
2100+
sleeptime=TimestampDifferenceMilliseconds(now,wakeup_time);
21072101
}
21082102

21092103
returnsleeptime;

‎src/backend/utils/adt/timestamp.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,12 +1623,14 @@ timeofday(PG_FUNCTION_ARGS)
16231623
* TimestampDifference -- convert the difference between two timestamps
16241624
*into integer seconds and microseconds
16251625
*
1626+
* This is typically used to calculate a wait timeout for select(2),
1627+
* which explains the otherwise-odd choice of output format.
1628+
*
16261629
* Both inputs must be ordinary finite timestamps (in current usage,
16271630
* they'll be results from GetCurrentTimestamp()).
16281631
*
1629-
* We expect start_time <= stop_time. If not, we return zeros; for current
1630-
* callers there is no need to be tense about which way division rounds on
1631-
* negative inputs.
1632+
* We expect start_time <= stop_time. If not, we return zeros,
1633+
* since then we're already past the previously determined stop_time.
16321634
*/
16331635
void
16341636
TimestampDifference(TimestampTzstart_time,TimestampTzstop_time,
@@ -1648,6 +1650,36 @@ TimestampDifference(TimestampTz start_time, TimestampTz stop_time,
16481650
}
16491651
}
16501652

1653+
/*
1654+
* TimestampDifferenceMilliseconds -- convert the difference between two
1655+
* timestamps into integer milliseconds
1656+
*
1657+
* This is typically used to calculate a wait timeout for WaitLatch()
1658+
* or a related function. The choice of "long" as the result type
1659+
* is to harmonize with that. It is caller's responsibility that the
1660+
* input timestamps not be so far apart as to risk overflow of "long"
1661+
* (which'd happen at about 25 days on machines with 32-bit "long").
1662+
*
1663+
* Both inputs must be ordinary finite timestamps (in current usage,
1664+
* they'll be results from GetCurrentTimestamp()).
1665+
*
1666+
* We expect start_time <= stop_time. If not, we return zero,
1667+
* since then we're already past the previously determined stop_time.
1668+
*
1669+
* Note we round up any fractional millisecond, since waiting for just
1670+
* less than the intended timeout is undesirable.
1671+
*/
1672+
long
1673+
TimestampDifferenceMilliseconds(TimestampTzstart_time,TimestampTzstop_time)
1674+
{
1675+
TimestampTzdiff=stop_time-start_time;
1676+
1677+
if (diff <=0)
1678+
return0;
1679+
else
1680+
return (long) ((diff+999) /1000);
1681+
}
1682+
16511683
/*
16521684
* TimestampDifferenceExceeds -- report whether the difference between two
16531685
*timestamps is >= a threshold (expressed in milliseconds)

‎src/include/utils/timestamp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ extern TimestampTz GetSQLCurrentTimestamp(int32 typmod);
7272
externTimestampGetSQLLocalTimestamp(int32typmod);
7373
externvoidTimestampDifference(TimestampTzstart_time,TimestampTzstop_time,
7474
long*secs,int*microsecs);
75+
externlongTimestampDifferenceMilliseconds(TimestampTzstart_time,
76+
TimestampTzstop_time);
7577
externboolTimestampDifferenceExceeds(TimestampTzstart_time,
7678
TimestampTzstop_time,
7779
intmsec);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp