Skip to content

Commit 79e0f87

Browse files
committed
Use type "int64" for memory accounting in tuplesort.c/tuplestore.c.
Commit 263865a switched tuplesort.c and tuplestore.c variables representing memory usage from type "long" to type "Size". This was unnecessary; I thought doing so avoided overflow scenarios on 64-bit Windows, but guc.c already limited work_mem so as to prevent the overflow. It was also incomplete, not touching the logic that assumed a signed data type. Change the affected variables to "int64". This is perfect for 64-bit platforms, and it reduces the need to contemplate platform-specific overflow scenarios. It also puts us close to being able to support work_mem over 2 GiB on 64-bit Windows. Per report from Andres Freund.
1 parent 7842d41 commit 79e0f87

File tree

3 files changed

+25
-21
lines changed

3 files changed

+25
-21
lines changed

src/backend/utils/sort/tuplesort.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ struct Tuplesortstate
211211
* tuples to return? */
212212
bool boundUsed; /* true if we made use of a bounded heap */
213213
int bound; /* if bounded, the maximum number of tuples */
214-
Size availMem; /* remaining memory available, in bytes */
215-
Size allowedMem; /* total memory allowed, in bytes */
214+
int64 availMem; /* remaining memory available, in bytes */
215+
int64 allowedMem; /* total memory allowed, in bytes */
216216
int maxTapes; /* number of tapes (Knuth's T) */
217217
int tapeRange; /* maxTapes-1 (Knuth's P) */
218218
MemoryContext sortcontext; /* memory context holding all sort data */
@@ -308,7 +308,7 @@ struct Tuplesortstate
308308
int *mergenext; /* first preread tuple for each source */
309309
int *mergelast; /* last preread tuple for each source */
310310
int *mergeavailslots; /* slots left for prereading each tape */
311-
Size *mergeavailmem; /* availMem for prereading each tape */
311+
int64 *mergeavailmem; /* availMem for prereading each tape */
312312
int mergefreelist; /* head of freelist of recycled slots */
313313
int mergefirstfree; /* first slot never used in this merge */
314314

@@ -565,7 +565,7 @@ tuplesort_begin_common(int workMem, bool randomAccess)
565565
state->randomAccess = randomAccess;
566566
state->bounded = false;
567567
state->boundUsed = false;
568-
state->allowedMem = workMem * 1024L;
568+
state->allowedMem = workMem * (int64) 1024;
569569
state->availMem = state->allowedMem;
570570
state->sortcontext = sortcontext;
571571
state->tapeset = NULL;
@@ -980,7 +980,7 @@ grow_memtuples(Tuplesortstate *state)
980980
{
981981
int newmemtupsize;
982982
int memtupsize = state->memtupsize;
983-
Size memNowUsed = state->allowedMem - state->availMem;
983+
int64 memNowUsed = state->allowedMem - state->availMem;
984984

985985
/* Forget it if we've already maxed out memtuples, per comment above */
986986
if (!state->growmemtuples)
@@ -991,7 +991,7 @@ grow_memtuples(Tuplesortstate *state)
991991
{
992992
/*
993993
* We've used no more than half of allowedMem; double our usage,
994-
* clamping at INT_MAX.
994+
* clamping at INT_MAX tuples.
995995
*/
996996
if (memtupsize < INT_MAX / 2)
997997
newmemtupsize = memtupsize * 2;
@@ -1048,7 +1048,9 @@ grow_memtuples(Tuplesortstate *state)
10481048
/*
10491049
* On a 32-bit machine, allowedMem could exceed MaxAllocHugeSize. Clamp
10501050
* to ensure our request won't be rejected. Note that we can easily
1051-
* exhaust address space before facing this outcome.
1051+
* exhaust address space before facing this outcome. (This is presently
1052+
* impossible due to guc.c's MAX_KILOBYTES limitation on work_mem, but
1053+
* don't rely on that at this distance.)
10521054
*/
10531055
if ((Size) newmemtupsize >= MaxAllocHugeSize / sizeof(SortTuple))
10541056
{
@@ -1067,7 +1069,7 @@ grow_memtuples(Tuplesortstate *state)
10671069
* palloc would be treating both old and new arrays as separate chunks.
10681070
* But we'll check LACKMEM explicitly below just in case.)
10691071
*/
1070-
if (state->availMem < (Size) ((newmemtupsize - memtupsize) * sizeof(SortTuple)))
1072+
if (state->availMem < (int64) ((newmemtupsize - memtupsize) * sizeof(SortTuple)))
10711073
goto noalloc;
10721074

10731075
/* OK, do it */
@@ -1722,7 +1724,7 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
17221724
* This is exported for use by the planner. allowedMem is in bytes.
17231725
*/
17241726
int
1725-
tuplesort_merge_order(Size allowedMem)
1727+
tuplesort_merge_order(int64 allowedMem)
17261728
{
17271729
int mOrder;
17281730

@@ -1756,7 +1758,7 @@ inittapes(Tuplesortstate *state)
17561758
int maxTapes,
17571759
ntuples,
17581760
j;
1759-
Size tapeSpace;
1761+
int64 tapeSpace;
17601762

17611763
/* Compute number of tapes to use: merge order plus 1 */
17621764
maxTapes = tuplesort_merge_order(state->allowedMem) + 1;
@@ -1805,7 +1807,7 @@ inittapes(Tuplesortstate *state)
18051807
state->mergenext = (int *) palloc0(maxTapes * sizeof(int));
18061808
state->mergelast = (int *) palloc0(maxTapes * sizeof(int));
18071809
state->mergeavailslots = (int *) palloc0(maxTapes * sizeof(int));
1808-
state->mergeavailmem = (Size *) palloc0(maxTapes * sizeof(Size));
1810+
state->mergeavailmem = (int64 *) palloc0(maxTapes * sizeof(int64));
18091811
state->tp_fib = (int *) palloc0(maxTapes * sizeof(int));
18101812
state->tp_runs = (int *) palloc0(maxTapes * sizeof(int));
18111813
state->tp_dummy = (int *) palloc0(maxTapes * sizeof(int));
@@ -2033,7 +2035,7 @@ mergeonerun(Tuplesortstate *state)
20332035
int srcTape;
20342036
int tupIndex;
20352037
SortTuple *tup;
2036-
Size priorAvail,
2038+
int64 priorAvail,
20372039
spaceFreed;
20382040

20392041
/*
@@ -2107,7 +2109,7 @@ beginmerge(Tuplesortstate *state)
21072109
int tapenum;
21082110
int srcTape;
21092111
int slotsPerTape;
2110-
Size spacePerTape;
2112+
int64 spacePerTape;
21112113

21122114
/* Heap should be empty here */
21132115
Assert(state->memtupcount == 0);
@@ -2228,7 +2230,7 @@ mergeprereadone(Tuplesortstate *state, int srcTape)
22282230
unsigned int tuplen;
22292231
SortTuple stup;
22302232
int tupIndex;
2231-
Size priorAvail,
2233+
int64 priorAvail,
22322234
spaceUsed;
22332235

22342236
if (!state->mergeactive[srcTape])

src/backend/utils/sort/tuplestore.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ struct Tuplestorestate
104104
bool backward; /* store extra length words in file? */
105105
bool interXact; /* keep open through transactions? */
106106
bool truncated; /* tuplestore_trim has removed tuples? */
107-
Size availMem; /* remaining memory available, in bytes */
108-
Size allowedMem; /* total memory allowed, in bytes */
107+
int64 availMem; /* remaining memory available, in bytes */
108+
int64 allowedMem; /* total memory allowed, in bytes */
109109
BufFile *myfile; /* underlying file, or NULL if none */
110110
MemoryContext context; /* memory context for holding tuples */
111111
ResourceOwner resowner; /* resowner for holding temp files */
@@ -550,7 +550,7 @@ grow_memtuples(Tuplestorestate *state)
550550
{
551551
int newmemtupsize;
552552
int memtupsize = state->memtupsize;
553-
Size memNowUsed = state->allowedMem - state->availMem;
553+
int64 memNowUsed = state->allowedMem - state->availMem;
554554

555555
/* Forget it if we've already maxed out memtuples, per comment above */
556556
if (!state->growmemtuples)
@@ -561,7 +561,7 @@ grow_memtuples(Tuplestorestate *state)
561561
{
562562
/*
563563
* We've used no more than half of allowedMem; double our usage,
564-
* clamping at INT_MAX.
564+
* clamping at INT_MAX tuples.
565565
*/
566566
if (memtupsize < INT_MAX / 2)
567567
newmemtupsize = memtupsize * 2;
@@ -618,7 +618,9 @@ grow_memtuples(Tuplestorestate *state)
618618
/*
619619
* On a 32-bit machine, allowedMem could exceed MaxAllocHugeSize. Clamp
620620
* to ensure our request won't be rejected. Note that we can easily
621-
* exhaust address space before facing this outcome.
621+
* exhaust address space before facing this outcome. (This is presently
622+
* impossible due to guc.c's MAX_KILOBYTES limitation on work_mem, but
623+
* don't rely on that at this distance.)
622624
*/
623625
if ((Size) newmemtupsize >= MaxAllocHugeSize / sizeof(void *))
624626
{
@@ -637,7 +639,7 @@ grow_memtuples(Tuplestorestate *state)
637639
* palloc would be treating both old and new arrays as separate chunks.
638640
* But we'll check LACKMEM explicitly below just in case.)
639641
*/
640-
if (state->availMem < (Size) ((newmemtupsize - memtupsize) * sizeof(void *)))
642+
if (state->availMem < (int64) ((newmemtupsize - memtupsize) * sizeof(void *)))
641643
goto noalloc;
642644

643645
/* OK, do it */

src/include/utils/tuplesort.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extern void tuplesort_get_stats(Tuplesortstate *state,
106106
const char **spaceType,
107107
long *spaceUsed);
108108

109-
extern int tuplesort_merge_order(Size allowedMem);
109+
extern int tuplesort_merge_order(int64 allowedMem);
110110

111111
/*
112112
* These routines may only be called if randomAccess was specified 'true'.

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