@@ -299,17 +299,36 @@ make_profile_hash()
299299
300300/*
301301 * Delta between two timestamps in milliseconds.
302+ * Also save microsecs to calculate rounding
302303 */
303304static int64
304- millisecs_diff (TimestampTz tz1 ,TimestampTz tz2 )
305+ millisecs_diff (TimestampTz tz1 ,TimestampTz tz2 , int * microsecs )
305306{
306- long secs ;
307- int microsecs ;
307+ long secs ;
308308
309- TimestampDifference (tz1 ,tz2 ,& secs ,& microsecs );
309+ TimestampDifference (tz1 ,tz2 ,& secs ,microsecs );
310310
311- return secs * 1000 + microsecs /1000 ;
311+ return secs * 1000 + * microsecs /1000 ;
312+ }
312313
314+ /*
315+ * Calculate time (in milliseconds) between two samples considering leftovers
316+ */
317+ static void
318+ calculate_elapsed (int64 * elapsed ,int64 * leftovers ,int period ,
319+ TimestampTz start ,TimestampTz end )
320+ {
321+ int microsecs = 0 ;
322+
323+ * elapsed += millisecs_diff (start ,end ,& microsecs );
324+ * leftovers += microsecs %1000 ;
325+
326+ /* If leftovers are at least 1 microsecond */
327+ if (* leftovers >=1000 )
328+ {
329+ * elapsed += * leftovers /1000 ;
330+ * leftovers %=1000 ;
331+ }
313332}
314333
315334/*
@@ -323,8 +342,12 @@ pgws_collector_main(Datum main_arg)
323342MemoryContext old_context ,
324343collector_context ;
325344TimestampTz current_ts ,
326- history_ts ,
327- profile_ts ;
345+ previous_ts ;
346+ /* in microsecs */
347+ int64 rounding_leftovers_history = 0 ,
348+ rounding_leftovers_profile = 0 ;
349+ int64 time_elapsed_history = 0 ,
350+ time_elapsed_profile = 0 ;
328351
329352/*
330353 * Establish signal handlers.
@@ -359,16 +382,15 @@ pgws_collector_main(Datum main_arg)
359382ereport (LOG , (errmsg ("pg_wait_sampling collector started" )));
360383
361384/* Start counting time for history and profile samples */
362- profile_ts = history_ts = GetCurrentTimestamp ();
385+ previous_ts = GetCurrentTimestamp ();
363386
364387while (1 )
365388{
366389int rc ;
367390shm_mq_handle * mqh ;
368- int64 history_diff ,
369- profile_diff ;
370391bool write_history ,
371392write_profile ;
393+ int time_to_sleep ;
372394
373395/* We need an explicit call for at least ProcSignal notifications. */
374396CHECK_FOR_INTERRUPTS ();
@@ -382,30 +404,54 @@ pgws_collector_main(Datum main_arg)
382404/* Calculate time to next sample for history or profile */
383405current_ts = GetCurrentTimestamp ();
384406
385- history_diff = millisecs_diff (history_ts ,current_ts );
386- profile_diff = millisecs_diff (profile_ts ,current_ts );
407+ calculate_elapsed (& time_elapsed_history ,& rounding_leftovers_history ,
408+ pgws_historyPeriod ,previous_ts ,current_ts );
409+ calculate_elapsed (& time_elapsed_profile ,& rounding_leftovers_profile ,
410+ pgws_profilePeriod ,previous_ts ,current_ts );
387411
388- write_history = (history_diff >= (int64 )pgws_historyPeriod );
389- write_profile = (profile_diff >= (int64 )pgws_profilePeriod );
412+ write_history = (time_elapsed_history >= (int64 )pgws_historyPeriod );
413+ write_profile = (time_elapsed_profile >= (int64 )pgws_profilePeriod );
390414
391415if (write_history || write_profile )
392416{
393417probe_waits (& observations ,profile_hash ,
394418write_history ,write_profile ,pgws_profilePid );
395-
419+ previous_ts = current_ts ;
396420if (write_history )
397421{
398- history_ts = current_ts ;
399- history_diff = 0 ;
422+ while (time_elapsed_history >=pgws_historyPeriod )
423+ {
424+ /*
425+ * Normally, this will happen only once, but if processor
426+ * is working overtime, time_elapsed could mount up.
427+ * We deliberately skip some samplings (well, we don't force
428+ * additional ones) in such case
429+ */
430+ time_elapsed_history -= pgws_historyPeriod ;
431+ }
400432}
401-
402433if (write_profile )
403434{
404- profile_ts = current_ts ;
405- profile_diff = 0 ;
435+ while (time_elapsed_profile >=pgws_profilePeriod )
436+ {
437+ /*
438+ * Normally, this will happen only once, but if processor
439+ * is working overtime, time_elapsed could mount up.
440+ * We deliberately skip some samplings (well, we don't force
441+ * additional ones) in such case
442+ */
443+ time_elapsed_profile -= pgws_profilePeriod ;
444+ }
406445}
407446}
408447
448+ /* Calculate how much time we have to sleep until any next sampling */
449+ time_to_sleep = Min (pgws_historyPeriod - (int )time_elapsed_history ,
450+ pgws_profilePeriod - (int )time_elapsed_profile );
451+
452+ if (time_to_sleep < 0 )
453+ time_to_sleep = 0 ;
454+
409455/* Shutdown if requested */
410456if (shutdown_requested )
411457break ;
@@ -415,8 +461,7 @@ pgws_collector_main(Datum main_arg)
415461 * shared memory.
416462 */
417463rc = WaitLatch (& MyProc -> procLatch ,WL_LATCH_SET |WL_TIMEOUT |WL_POSTMASTER_DEATH ,
418- Min (pgws_historyPeriod - (int )history_diff ,
419- pgws_historyPeriod - (int )profile_diff ),PG_WAIT_EXTENSION );
464+ time_to_sleep ,PG_WAIT_EXTENSION );
420465
421466if (rc & WL_POSTMASTER_DEATH )
422467proc_exit (1 );