Display explain buffers measurements in memory units rather than blocks. Also show...
authorGreg Stark <stark@mit.edu>
Mon, 15 Feb 2010 02:36:26 +0000 (02:36 +0000)
committerGreg Stark <stark@mit.edu>
Mon, 15 Feb 2010 02:36:26 +0000 (02:36 +0000)
src/backend/commands/explain.c

index 8c9b060e6bdafa146b50336adc81fc35e558a171..38ccc845854cf72311d97d3fbfb9b0da148e1940 100644 (file)
@@ -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;
+}