Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9fba1ed

Browse files
committed
Adjust tuplestore stats API
1eff827 added an API to tuplestore.c to allow callers to obtain storage telemetry data. That API wasn't quite good enough for callers that perform tuplestore_clear() as the telemetry functions only accounted for the current state of the tuplestore, not the maximums before tuplestore_clear() was called. There's a pending patch that would like to add tuplestore telemetry output to EXPLAIN ANALYZE for WindowAgg. That node type uses tuplestore_clear() before moving to the next window partition and we want to show the maximum space used, not the space used for the final partition. Reviewed-by: Tatsuo Ishii, Ashutosh Bapat Discussion: https://postgres/m/CAApHDvoY8cibGcicLV0fNh=9JVx9PANcWvhkdjBnDCc9Quqytg@mail.gmail.com
1 parent e6c45d8 commit 9fba1ed

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

src/backend/commands/explain.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3350,8 +3350,9 @@ static void
33503350
show_material_info(MaterialState *mstate, ExplainState *es)
33513351
{
33523352
Tuplestorestate *tupstore = mstate->tuplestorestate;
3353-
const char *storageType;
3354-
int64 spaceUsedKB;
3353+
char *maxStorageType;
3354+
int64 maxSpaceUsed,
3355+
maxSpaceUsedKB;
33553356

33563357
/*
33573358
* Nothing to show if ANALYZE option wasn't used or if execution didn't
@@ -3360,21 +3361,21 @@ show_material_info(MaterialState *mstate, ExplainState *es)
33603361
if (!es->analyze || tupstore == NULL)
33613362
return;
33623363

3363-
storageType = tuplestore_storage_type_name(tupstore);
3364-
spaceUsedKB = BYTES_TO_KILOBYTES(tuplestore_space_used(tupstore));
3364+
tuplestore_get_stats(tupstore, &maxStorageType, &maxSpaceUsed);
3365+
maxSpaceUsedKB = BYTES_TO_KILOBYTES(maxSpaceUsed);
33653366

33663367
if (es->format != EXPLAIN_FORMAT_TEXT)
33673368
{
3368-
ExplainPropertyText("Storage", storageType, es);
3369-
ExplainPropertyInteger("Maximum Storage", "kB", spaceUsedKB, es);
3369+
ExplainPropertyText("Storage", maxStorageType, es);
3370+
ExplainPropertyInteger("Maximum Storage", "kB", maxSpaceUsedKB, es);
33703371
}
33713372
else
33723373
{
33733374
ExplainIndentText(es);
33743375
appendStringInfo(es->str,
33753376
"Storage: %s Maximum Storage: " INT64_FORMAT "kB\n",
3376-
storageType,
3377-
spaceUsedKB);
3377+
maxStorageType,
3378+
maxSpaceUsedKB);
33783379
}
33793380
}
33803381

src/backend/utils/sort/tuplestore.c

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ struct Tuplestorestate
107107
bool backward; /* store extra length words in file? */
108108
bool interXact; /* keep open through transactions? */
109109
bool truncated; /* tuplestore_trim has removed tuples? */
110+
bool usedDisk; /* used by tuplestore_get_stats() */
111+
int64 maxSpace; /* used by tuplestore_get_stats() */
110112
int64 availMem; /* remaining memory available, in bytes */
111113
int64 allowedMem; /* total memory allowed, in bytes */
112-
int64 maxSpace; /* maximum space used in memory */
113114
int64 tuples; /* number of tuples added */
114115
BufFile *myfile; /* underlying file, or NULL if none */
115116
MemoryContext context; /* memory context for holding tuples */
@@ -262,9 +263,10 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes)
262263
state->eflags = eflags;
263264
state->interXact = interXact;
264265
state->truncated = false;
266+
state->usedDisk = false;
267+
state->maxSpace = 0;
265268
state->allowedMem = maxKBytes * 1024L;
266269
state->availMem = state->allowedMem;
267-
state->maxSpace = 0;
268270
state->myfile = NULL;
269271

270272
/*
@@ -870,6 +872,14 @@ tuplestore_puttuple_common(Tuplestorestate *state, void *tuple)
870872
* though callers might drop the requirement.
871873
*/
872874
state->backward = (state->eflags & EXEC_FLAG_BACKWARD) != 0;
875+
876+
/*
877+
* Update the maximum space used before dumping the tuples. It's
878+
* possible that more space will be used by the tuples in memory
879+
* than the space that will be used on disk.
880+
*/
881+
tuplestore_updatemax(state);
882+
873883
state->status = TSS_WRITEFILE;
874884
dumptuples(state);
875885
break;
@@ -1444,7 +1454,7 @@ tuplestore_trim(Tuplestorestate *state)
14441454
Assert(nremove >= state->memtupdeleted);
14451455
Assert(nremove <= state->memtupcount);
14461456

1447-
/* before freeing any memory, update maxSpace */
1457+
/* before freeing any memory, update the statistics */
14481458
tuplestore_updatemax(state);
14491459

14501460
/* Release no-longer-needed tuples */
@@ -1491,45 +1501,46 @@ tuplestore_trim(Tuplestorestate *state)
14911501

14921502
/*
14931503
* tuplestore_updatemax
1494-
* Update maxSpace field
1504+
* Update the maximum space used by this tuplestore and the method used
1505+
* for storage.
14951506
*/
14961507
static void
14971508
tuplestore_updatemax(Tuplestorestate *state)
14981509
{
14991510
if (state->status == TSS_INMEM)
15001511
state->maxSpace = Max(state->maxSpace,
15011512
state->allowedMem - state->availMem);
1502-
}
1503-
1504-
/*
1505-
* tuplestore_storage_type_name
1506-
* Return a string description of the storage method used to store the
1507-
* tuples.
1508-
*/
1509-
const char *
1510-
tuplestore_storage_type_name(Tuplestorestate *state)
1511-
{
1512-
if (state->status == TSS_INMEM)
1513-
return "Memory";
15141513
else
1515-
return "Disk";
1514+
{
1515+
state->maxSpace = Max(state->maxSpace,
1516+
BufFileSize(state->myfile));
1517+
1518+
/*
1519+
* usedDisk never gets set to false again after spilling to disk, even
1520+
* if tuplestore_clear() is called and new tuples go to memory again.
1521+
*/
1522+
state->usedDisk = true;
1523+
}
15161524
}
15171525

15181526
/*
1519-
* tuplestore_space_used
1520-
* Return the maximum space used in memory unless the tuplestore has spilled
1521-
* to disk, in which case, return the disk space used.
1527+
* tuplestore_get_stats
1528+
* Obtain statistics about the maximum space used by the tuplestore.
1529+
* These statistics are the maximums and are not reset by calls to
1530+
* tuplestore_trim() or tuplestore_clear().
15221531
*/
1523-
int64
1524-
tuplestore_space_used(Tuplestorestate *state)
1532+
void
1533+
tuplestore_get_stats(Tuplestorestate *state, char **max_storage_type,
1534+
int64 *max_space)
15251535
{
1526-
/* First, update the maxSpace field */
15271536
tuplestore_updatemax(state);
15281537

1529-
if (state->status == TSS_INMEM)
1530-
return state->maxSpace;
1538+
if (state->usedDisk)
1539+
*max_storage_type = "Disk";
15311540
else
1532-
return BufFileSize(state->myfile);
1541+
*max_storage_type = "Memory";
1542+
1543+
*max_space = state->maxSpace;
15331544
}
15341545

15351546
/*
@@ -1601,7 +1612,6 @@ writetup_heap(Tuplestorestate *state, void *tup)
16011612
if (state->backward) /* need trailing length word? */
16021613
BufFileWrite(state->myfile, &tuplen, sizeof(tuplen));
16031614

1604-
/* no need to call tuplestore_updatemax() when not in TSS_INMEM */
16051615
FREEMEM(state, GetMemoryChunkSpace(tuple));
16061616
heap_free_minimal_tuple(tuple);
16071617
}

src/include/utils/tuplestore.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ extern void tuplestore_copy_read_pointer(Tuplestorestate *state,
6565

6666
extern void tuplestore_trim(Tuplestorestate *state);
6767

68-
extern const char *tuplestore_storage_type_name(Tuplestorestate *state);
69-
70-
extern int64 tuplestore_space_used(Tuplestorestate *state);
68+
extern void tuplestore_get_stats(Tuplestorestate *state, char **storage_type,
69+
int64 *max_space);
7170

7271
extern bool tuplestore_in_memory(Tuplestorestate *state);
7372

0 commit comments

Comments
 (0)