Skip to content

Commit 097366c

Browse files
committed
Move memory management away from writetup() and tuplesort_put*()
This commit puts some generic work away from sort-variant-specific function. In particular, tuplesort_put*() now doesn't need to decrease available memory and switch to sort context before calling puttuple_common(). writetup() doesn't need to free SortTuple.tuple and increase available memory. Discussion: https://postgr.es/m/CAPpHfdvjix0Ahx-H3Jp1M2R%2B_74P-zKnGGygx4OWr%3DbUQ8BNdw%40mail.gmail.com Author: Alexander Korotkov Reviewed-by: Pavel Borisov, Maxim Orlov, Matthias van de Meent Reviewed-by: Andres Freund, John Naylor
1 parent 033dd02 commit 097366c

File tree

1 file changed

+33
-45
lines changed

1 file changed

+33
-45
lines changed

src/backend/utils/sort/tuplesort.c

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,7 @@ struct Tuplesortstate
288288

289289
/*
290290
* Function to write a stored tuple onto tape. The representation of the
291-
* tuple on tape need not be the same as it is in memory; requirements on
292-
* the tape representation are given below. Unless the slab allocator is
293-
* used, after writing the tuple, pfree() the out-of-line data (not the
294-
* SortTuple struct!), and increase state->availMem by the amount of
295-
* memory space thereby released.
291+
* tuple on tape need not be the same as it is in memory.
296292
*/
297293
void (*writetup) (Tuplesortstate *state, LogicalTape *tape,
298294
SortTuple *stup);
@@ -549,7 +545,7 @@ struct Sharedsort
549545

550546
#define REMOVEABBREV(state,stup,count) ((*(state)->removeabbrev) (state, stup, count))
551547
#define COMPARETUP(state,a,b) ((*(state)->comparetup) (a, b, state))
552-
#define WRITETUP(state,tape,stup) ((*(state)->writetup) (state, tape, stup))
548+
#define WRITETUP(state,tape,stup) (writetuple(state, tape, stup))
553549
#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
554550
#define LACKMEM(state) ((state)->availMem < 0 && !(state)->slabAllocatorUsed)
555551
#define USEMEM(state,amt) ((state)->availMem -= (amt))
@@ -618,6 +614,8 @@ static Tuplesortstate *tuplesort_begin_common(int workMem,
618614
static void tuplesort_begin_batch(Tuplesortstate *state);
619615
static void puttuple_common(Tuplesortstate *state, SortTuple *tuple,
620616
bool useAbbrev);
617+
static void writetuple(Tuplesortstate *state, LogicalTape *tape,
618+
SortTuple *stup);
621619
static bool consider_abort_common(Tuplesortstate *state);
622620
static void inittapes(Tuplesortstate *state, bool mergeruns);
623621
static void inittapestate(Tuplesortstate *state, int maxTapes);
@@ -1848,7 +1846,6 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
18481846
/* copy the tuple into sort storage */
18491847
tuple = ExecCopySlotMinimalTuple(slot);
18501848
stup.tuple = (void *) tuple;
1851-
USEMEM(state, GetMemoryChunkSpace(tuple));
18521849
/* set up first-column key value */
18531850
htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET;
18541851
htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET);
@@ -1857,8 +1854,6 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
18571854
state->tupDesc,
18581855
&stup.isnull1);
18591856

1860-
MemoryContextSwitchTo(state->sortcontext);
1861-
18621857
puttuple_common(state, &stup,
18631858
state->sortKeys->abbrev_converter && !stup.isnull1);
18641859

@@ -1879,9 +1874,6 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
18791874
/* copy the tuple into sort storage */
18801875
tup = heap_copytuple(tup);
18811876
stup.tuple = (void *) tup;
1882-
USEMEM(state, GetMemoryChunkSpace(tup));
1883-
1884-
MemoryContextSwitchTo(state->sortcontext);
18851877

18861878
/*
18871879
* set up first-column key value, and potentially abbreviate, if it's a
@@ -1910,27 +1902,21 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
19101902
ItemPointer self, Datum *values,
19111903
bool *isnull)
19121904
{
1913-
MemoryContext oldcontext;
19141905
SortTuple stup;
19151906
IndexTuple tuple;
19161907

19171908
stup.tuple = index_form_tuple_context(RelationGetDescr(rel), values,
19181909
isnull, state->tuplecontext);
19191910
tuple = ((IndexTuple) stup.tuple);
19201911
tuple->t_tid = *self;
1921-
USEMEM(state, GetMemoryChunkSpace(stup.tuple));
19221912
/* set up first-column key value */
19231913
stup.datum1 = index_getattr(tuple,
19241914
1,
19251915
RelationGetDescr(state->indexRel),
19261916
&stup.isnull1);
19271917

1928-
oldcontext = MemoryContextSwitchTo(state->sortcontext);
1929-
19301918
puttuple_common(state, &stup,
19311919
state->sortKeys && state->sortKeys->abbrev_converter && !stup.isnull1);
1932-
1933-
MemoryContextSwitchTo(oldcontext);
19341920
}
19351921

19361922
/*
@@ -1965,15 +1951,12 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
19651951
stup.datum1 = !isNull ? val : (Datum) 0;
19661952
stup.isnull1 = isNull;
19671953
stup.tuple = NULL; /* no separate storage */
1968-
MemoryContextSwitchTo(state->sortcontext);
19691954
}
19701955
else
19711956
{
19721957
stup.isnull1 = false;
19731958
stup.datum1 = datumCopy(val, false, state->datumTypeLen);
19741959
stup.tuple = DatumGetPointer(stup.datum1);
1975-
USEMEM(state, GetMemoryChunkSpace(stup.tuple));
1976-
MemoryContextSwitchTo(state->sortcontext);
19771960
}
19781961

19791962
puttuple_common(state, &stup,
@@ -1988,8 +1971,14 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
19881971
static void
19891972
puttuple_common(Tuplesortstate *state, SortTuple *tuple, bool useAbbrev)
19901973
{
1974+
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
1975+
19911976
Assert(!LEADER(state));
19921977

1978+
/* Count the size of the out-of-line data */
1979+
if (tuple->tuple != NULL)
1980+
USEMEM(state, GetMemoryChunkSpace(tuple->tuple));
1981+
19931982
if (!useAbbrev)
19941983
{
19951984
/*
@@ -2062,14 +2051,18 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple, bool useAbbrev)
20622051
pg_rusage_show(&state->ru_start));
20632052
#endif
20642053
make_bounded_heap(state);
2054+
MemoryContextSwitchTo(oldcontext);
20652055
return;
20662056
}
20672057

20682058
/*
20692059
* Done if we still fit in available memory and have array slots.
20702060
*/
20712061
if (state->memtupcount < state->memtupsize && !LACKMEM(state))
2062+
{
2063+
MemoryContextSwitchTo(oldcontext);
20722064
return;
2065+
}
20732066

20742067
/*
20752068
* Nope; time to switch to tape-based operation.
@@ -2123,6 +2116,25 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple, bool useAbbrev)
21232116
elog(ERROR, "invalid tuplesort state");
21242117
break;
21252118
}
2119+
MemoryContextSwitchTo(oldcontext);
2120+
}
2121+
2122+
/*
2123+
* Write a stored tuple onto tape.tuple. Unless the slab allocator is
2124+
* used, after writing the tuple, pfree() the out-of-line data (not the
2125+
* SortTuple struct!), and increase state->availMem by the amount of
2126+
* memory space thereby released.
2127+
*/
2128+
static void
2129+
writetuple(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
2130+
{
2131+
state->writetup(state, tape, stup);
2132+
2133+
if (!state->slabAllocatorUsed && stup->tuple)
2134+
{
2135+
FREEMEM(state, GetMemoryChunkSpace(stup->tuple));
2136+
pfree(stup->tuple);
2137+
}
21262138
}
21272139

21282140
static bool
@@ -3960,12 +3972,6 @@ writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
39603972
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
39613973
* word? */
39623974
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
3963-
3964-
if (!state->slabAllocatorUsed)
3965-
{
3966-
FREEMEM(state, GetMemoryChunkSpace(tuple));
3967-
heap_free_minimal_tuple(tuple);
3968-
}
39693975
}
39703976

39713977
static void
@@ -4141,12 +4147,6 @@ writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
41414147
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
41424148
* word? */
41434149
LogicalTapeWrite(tape, &tuplen, sizeof(tuplen));
4144-
4145-
if (!state->slabAllocatorUsed)
4146-
{
4147-
FREEMEM(state, GetMemoryChunkSpace(tuple));
4148-
heap_freetuple(tuple);
4149-
}
41504150
}
41514151

41524152
static void
@@ -4403,12 +4403,6 @@ writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
44034403
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
44044404
* word? */
44054405
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
4406-
4407-
if (!state->slabAllocatorUsed)
4408-
{
4409-
FREEMEM(state, GetMemoryChunkSpace(tuple));
4410-
pfree(tuple);
4411-
}
44124406
}
44134407

44144408
static void
@@ -4495,12 +4489,6 @@ writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
44954489
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
44964490
* word? */
44974491
LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen));
4498-
4499-
if (!state->slabAllocatorUsed && stup->tuple)
4500-
{
4501-
FREEMEM(state, GetMemoryChunkSpace(stup->tuple));
4502-
pfree(stup->tuple);
4503-
}
45044492
}
45054493

45064494
static void

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy