Improve readability of the output of psql's \timing command.

In addition to the existing decimal-milliseconds output value,
display the same value in mm:ss.fff format if it exceeds one second.
Tack on hours and even days fields if the interval is large enough.
This avoids needing mental arithmetic to convert the values into
customary time units.

Corey Huinker, reviewed by Gerdan Santos; bikeshedding by many

Discussion: <CADkLM=dbC4R8sbbuFXQVBFWoJGQkTEW8RWnC0PbW9nZsovZpJQ@mail.gmail.com>
This commit is contained in:
Tom Lane 2016-09-03 15:29:03 -04:00
parent 600dc4c0da
commit 6591f4226c
2 changed files with 59 additions and 4 deletions

View File

@ -2789,8 +2789,11 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
<term><literal>\timing [ <replaceable class="parameter">on</replaceable> | <replaceable class="parameter">off</replaceable> ]</literal></term>
<listitem>
<para>
Without parameter, toggles a display of how long each SQL statement
takes, in milliseconds. With parameter, sets same.
With a parameter, turns displaying of how long each SQL statement
takes on or off. Without a parameter, toggles the display between
on and off. The display is in milliseconds; intervals longer than
1 second are also shown in minutes:seconds format, with hours and
days fields added if needed.
</para>
</listitem>
</varlistentry>

View File

@ -10,6 +10,7 @@
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <signal.h>
#ifndef WIN32
#include <unistd.h> /* for write() */
@ -531,6 +532,57 @@ ClearOrSaveResult(PGresult *result)
}
/*
* Print microtiming output. Always print raw milliseconds; if the interval
* is >= 1 second, also break it down into days/hours/minutes/seconds.
*/
static void
PrintTiming(double elapsed_msec)
{
double seconds;
double minutes;
double hours;
double days;
if (elapsed_msec < 1000.0)
{
/* This is the traditional (pre-v10) output format */
printf(_("Time: %.3f ms\n"), elapsed_msec);
return;
}
/*
* Note: we could print just seconds, in a format like %06.3f, when the
* total is less than 1min. But that's hard to interpret unless we tack
* on "s" or otherwise annotate it. Forcing the display to include
* minutes seems like a better solution.
*/
seconds = elapsed_msec / 1000.0;
minutes = floor(seconds / 60.0);
seconds -= 60.0 * minutes;
if (minutes < 60.0)
{
printf(_("Time: %.3f ms (%02d:%06.3f)\n"),
elapsed_msec, (int) minutes, seconds);
return;
}
hours = floor(minutes / 60.0);
minutes -= 60.0 * hours;
if (hours < 24.0)
{
printf(_("Time: %.3f ms (%02d:%02d:%06.3f)\n"),
elapsed_msec, (int) hours, (int) minutes, seconds);
return;
}
days = floor(hours / 24.0);
hours -= 24.0 * days;
printf(_("Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n"),
elapsed_msec, days, (int) hours, (int) minutes, seconds);
}
/*
* PSQLexec
*
@ -679,7 +731,7 @@ PSQLexecWatch(const char *query, const printQueryOpt *opt)
/* Possible microtiming output */
if (pset.timing)
printf(_("Time: %.3f ms\n"), elapsed_msec);
PrintTiming(elapsed_msec);
return 1;
}
@ -1332,7 +1384,7 @@ SendQuery(const char *query)
/* Possible microtiming output */
if (pset.timing)
printf(_("Time: %.3f ms\n"), elapsed_msec);
PrintTiming(elapsed_msec);
/* check for events that may occur during query execution */