<!--
-$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.23 2005/09/24 23:25:31 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.24 2005/10/03 22:55:50 tgl Exp $
-->
<chapter Id="runtime-config">
<title>Run-time Configuration</title>
</listitem>
</varlistentry>
+ <varlistentry id="guc-trace-sort" xreflabel="trace_sort">
+ <term><varname>trace_sort</varname> (<type>boolean</type>)</term>
+ <indexterm>
+ <primary><varname>trace_sort</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ If on, emit information about resource usage during sort operations.
+ This option is only available if the <symbol>TRACE_SORT</symbol> macro
+ was defined when <productname>PostgreSQL</productname> was compiled.
+ (However, <symbol>TRACE_SORT</symbol> is currently defined by default.)
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>trace_locks</varname> (<type>boolean</type>)</term>
<term><varname>trace_lwlocks</varname> (<type>boolean</type>)</term>
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.289 2005/09/24 22:54:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.290 2005/10/03 22:55:51 tgl Exp $
*
*--------------------------------------------------------------------
*/
extern int CommitSiblings;
extern char *default_tablespace;
extern bool fullPageWrites;
+#ifdef TRACE_SORT
+extern bool trace_sort;
+#endif
static const char *assign_log_destination(const char *value,
bool doit, GucSource source);
false, NULL, NULL
},
+#ifdef TRACE_SORT
+ {
+ {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
+ gettext_noop("Emit information about resource usage in sorting."),
+ NULL,
+ GUC_NOT_IN_SAMPLE
+ },
+ &trace_sort,
+ false, NULL, NULL
+ },
+#endif
+
#ifdef WAL_DEBUG
{
{"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.50 2005/09/23 15:36:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.51 2005/10/03 22:55:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/logtape.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+#include "utils/pg_rusage.h"
#include "utils/syscache.h"
#include "utils/tuplesort.h"
+/* GUC variable */
+#ifdef TRACE_SORT
+bool trace_sort = false;
+#endif
+
+
/*
* Possible states of a Tuplesort object. These denote the states that
* persist between calls of Tuplesort routines.
/* we need typelen and byval in order to know how to copy the Datums. */
int datumTypeLen;
bool datumTypeByVal;
+
+ /*
+ * Resource snapshot for time of sort start.
+ */
+#ifdef TRACE_SORT
+ PGRUsage ru_start;
+#endif
};
#define COMPARETUP(state,a,b) ((*(state)->comparetup) (state, a, b))
state = (Tuplesortstate *) palloc0(sizeof(Tuplesortstate));
+#ifdef TRACE_SORT
+ if (trace_sort)
+ pg_rusage_init(&state->ru_start);
+#endif
+
state->status = TSS_INITIAL;
state->randomAccess = randomAccess;
state->availMem = workMem * 1024L;
AssertArg(nkeys > 0);
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE,
+ "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c",
+ nkeys, workMem, randomAccess ? 't' : 'f');
+#endif
+
state->comparetup = comparetup_heap;
state->copytup = copytup_heap;
state->writetup = writetup_heap;
{
Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE,
+ "begin index sort: unique = %c, workMem = %d, randomAccess = %c",
+ enforceUnique ? 't' : 'f',
+ workMem, randomAccess ? 't' : 'f');
+#endif
+
state->comparetup = comparetup_index;
state->copytup = copytup_index;
state->writetup = writetup_index;
int16 typlen;
bool typbyval;
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE,
+ "begin datum sort: workMem = %d, randomAccess = %c",
+ workMem, randomAccess ? 't' : 'f');
+#endif
+
state->comparetup = comparetup_datum;
state->copytup = copytup_datum;
state->writetup = writetup_datum;
if (state->sortFnKinds)
pfree(state->sortFnKinds);
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE, "sort ended: %s",
+ pg_rusage_show(&state->ru_start));
+#endif
+
pfree(state);
}
void
tuplesort_performsort(Tuplesortstate *state)
{
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE, "performsort starting: %s",
+ pg_rusage_show(&state->ru_start));
+#endif
+
switch (state->status)
{
case TSS_INITIAL:
elog(ERROR, "invalid tuplesort state");
break;
}
+
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE, "performsort done%s: %s",
+ (state->status == TSS_FINALMERGE) ? " (except final merge)" : "",
+ pg_rusage_show(&state->ru_start));
+#endif
}
/*
int ntuples,
j;
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE, "switching to external sort: %s",
+ pg_rusage_show(&state->ru_start));
+#endif
+
state->tapeset = LogicalTapeSetCreate(MAXTAPES);
/*
*/
markrunend(state, destTape);
state->tp_runs[TAPERANGE]++;
+
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE, "finished merge step: %s",
+ pg_rusage_show(&state->ru_start));
+#endif
}
/*
state->tp_runs[state->destTape]++;
state->tp_dummy[state->destTape]--; /* per Alg D step D2 */
+#ifdef TRACE_SORT
+ if (trace_sort)
+ elog(NOTICE, "finished writing%s run %d: %s",
+ (state->memtupcount == 0) ? " final" : "",
+ state->currentRun,
+ pg_rusage_show(&state->ru_start));
+#endif
+
/*
* Done if heap is empty, else prepare for new run.
*/