From 34ebccddcd234df7b4f25d6dd6355a886c831edb Mon Sep 17 00:00:00 2001 From: Greg Stark Date: Mon, 15 Feb 2010 02:36:26 +0000 Subject: [PATCH] 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 --- src/backend/commands/explain.c | 98 +++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 8c9b060e6b..38ccc84585 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; +}