summaryrefslogtreecommitdiff
path: root/src/backend/commands/explain.c
diff options
context:
space:
mode:
authorGreg Stark <stark@mit.edu>2010-02-15 02:36:26 +0000
committerGreg Stark <stark@mit.edu>2010-02-15 02:36:26 +0000
commit34ebccddcd234df7b4f25d6dd6355a886c831edb (patch)
tree25f3fed8972a269851982696f2ec76a6f3019b58 /src/backend/commands/explain.c
parentf8c183a1ac02aef14832c1f29946ef2bcb5866b7 (diff)
Display explain buffers measurements in memory units rather than blocks. Also show "Total Buffer Usage" to hint that these are totals not averages per loop
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r--src/backend/commands/explain.c98
1 files changed, 74 insertions, 24 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 8c9b060e6bd..38ccc845854 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.200 2010/02/01 15:43:35 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.201 2010/02/15 02:36:26 stark Exp $
*
*-------------------------------------------------------------------------
*/
@@ -98,6 +98,7 @@ static void ExplainJSONLineEnding(ExplainState *es);
static void ExplainYAMLLineStarting(ExplainState *es);
static void escape_json(StringInfo buf, const char *str);
static void escape_yaml(StringInfo buf, const char *str);
+static double normalize_memory(double amount, char **unit, int *precision);
/*
@@ -1081,47 +1082,63 @@ ExplainNode(Plan *plan, PlanState *planstate,
if (has_shared || has_local || has_temp)
{
appendStringInfoSpaces(es->str, es->indent * 2);
- appendStringInfoString(es->str, "Buffers:");
+ appendStringInfoString(es->str, "Total Buffer Usage:");
if (has_shared)
{
+ char *hit_unit, *read_unit, *written_unit;
+ int hit_prec, read_prec, written_prec;
+ double hit_mem = normalize_memory((double)usage->shared_blks_hit * BLCKSZ, &hit_unit, &hit_prec);
+ double read_mem = normalize_memory((double)usage->shared_blks_read * BLCKSZ, &read_unit, &read_prec);
+ double written_mem = normalize_memory((double)usage->shared_blks_written * BLCKSZ, &written_unit, &written_prec);
+
appendStringInfoString(es->str, " shared");
- if (usage->shared_blks_hit > 0)
- appendStringInfo(es->str, " hit=%ld",
- usage->shared_blks_hit);
+ appendStringInfo(es->str, " hit=%.*f%s",
+ hit_prec, hit_mem, hit_unit);
if (usage->shared_blks_read > 0)
- appendStringInfo(es->str, " read=%ld",
- usage->shared_blks_read);
+ appendStringInfo(es->str, " read=%.*f%s",
+ read_prec, read_mem, read_unit);
if (usage->shared_blks_written > 0)
- appendStringInfo(es->str, " written=%ld",
- usage->shared_blks_written);
+ appendStringInfo(es->str, " written=%.*f%s",
+ written_prec, written_mem, written_unit);
if (has_local || has_temp)
appendStringInfoChar(es->str, ',');
}
if (has_local)
{
- appendStringInfoString(es->str, " local");
- if (usage->local_blks_hit > 0)
- appendStringInfo(es->str, " hit=%ld",
- usage->local_blks_hit);
- if (usage->local_blks_read > 0)
- appendStringInfo(es->str, " read=%ld",
- usage->local_blks_read);
- if (usage->local_blks_written > 0)
- appendStringInfo(es->str, " written=%ld",
- usage->local_blks_written);
+ char *hit_unit, *read_unit, *written_unit;
+ int hit_prec, read_prec, written_prec;
+ double hit_mem = normalize_memory((double)usage->local_blks_hit * BLCKSZ, &hit_unit, &hit_prec);
+ double read_mem = normalize_memory((double)usage->local_blks_read * BLCKSZ, &read_unit, &read_prec);
+ double written_mem = normalize_memory((double)usage->local_blks_written * BLCKSZ, &written_unit, &written_prec);
+
+ appendStringInfoString(es->str, " local");
+ if (usage->local_blks_hit > 0)
+ appendStringInfo(es->str, " hit=%.*f%s",
+ hit_prec, hit_mem, hit_unit);
+ if (usage->local_blks_read > 0)
+ appendStringInfo(es->str, " read=%.*f%s",
+ read_prec, read_mem, read_unit);
+ if (usage->local_blks_written > 0)
+ appendStringInfo(es->str, " written=%.*f%s",
+ written_prec, written_mem, written_unit);
if (has_temp)
appendStringInfoChar(es->str, ',');
}
if (has_temp)
{
+ char *read_unit, *written_unit;
+ int read_prec, written_prec;
+ double read_mem = normalize_memory((double)usage->temp_blks_read * BLCKSZ, &read_unit, &read_prec);
+ double written_mem = normalize_memory((double)usage->temp_blks_written * BLCKSZ, &written_unit, &written_prec);
+
appendStringInfoString(es->str, " temp");
if (usage->temp_blks_read > 0)
- appendStringInfo(es->str, " read=%ld",
- usage->temp_blks_read);
- if (usage->temp_blks_written > 0)
- appendStringInfo(es->str, " written=%ld",
- usage->temp_blks_written);
+ appendStringInfo(es->str, " read=%.*f%s",
+ read_prec, read_mem, read_unit);
+ if (usage->temp_blks_written > 0)
+ appendStringInfo(es->str, " written=%.*f%s",
+ written_prec, written_mem, written_unit);
}
appendStringInfoChar(es->str, '\n');
}
@@ -2153,3 +2170,36 @@ escape_yaml(StringInfo buf, const char *str)
appendStringInfo(buf, "%s", str);
}
+
+/*
+ * For a quantity of bytes pick a reasonable display unit for it and
+ * return the quantity in that unit. Also return the unit name and a
+ * reasonable precision via the reference parameters.
+ */
+
+static double normalize_memory(double amount, char **unit, int *precision)
+{
+ static char *units[] = {"bytes", "kB", "MB", "GB", "TB", "PB"};
+ char **u = units, **last = units + (sizeof(units)/sizeof(*units)-1);
+
+ while (amount > 1024.0 && u < last)
+ {
+ amount /= 1024.0;
+ u += 1;
+ }
+
+ *unit = *u;
+
+ /* if it's bytes or kB then don't print decimals since that's less
+ * than blocksize, otherwise always print 3 significant digits */
+ if (u == units || u == units+1 )
+ *precision = 0;
+ else if (amount < 10)
+ *precision = 2;
+ else if (amount < 100)
+ *precision = 1;
+ else
+ *precision = 0;
+
+ return amount;
+}