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

Commit b34aa33

Browse files
committed
Modify logtape.c so that the initial LogicalTapeSetCreate call only
allocates the control data. The per-tape buffers are allocated only on first use. This saves memory in situations where tuplesort.c overestimates the number of tapes needed (ie, there are fewer runs than tapes). Also, this makes legitimate the coding in inittapes() that includes tape buffer space in the maximum-memory calculation: when inittapes runs, we've already expended the whole allowed memory on tuple storage, and so we'd better not allocate all the tape buffers until we've flushed some tuples out of memory.
1 parent df700e6 commit b34aa33

File tree

1 file changed

+57
-26
lines changed

1 file changed

+57
-26
lines changed

src/backend/utils/sort/logtape.c

+57-26
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
* Portions Copyright (c) 1994, Regents of the University of California
6565
*
6666
* IDENTIFICATION
67-
* $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.17 2005/10/18 22:59:37 tgl Exp $
67+
* $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.18 2006/02/19 05:58:36 tgl Exp $
6868
*
6969
*-------------------------------------------------------------------------
7070
*/
@@ -124,10 +124,10 @@ typedef struct LogicalTape
124124
* we do need the relative block number so we can detect end-of-tape while
125125
* reading.
126126
*/
127+
char *buffer; /* physical buffer (separately palloc'd) */
127128
long curBlockNumber; /* this block's logical blk# within tape */
128129
int pos; /* next read/write position in buffer */
129130
int nbytes; /* total # of valid bytes in buffer */
130-
char buffer[BLCKSZ];
131131
} LogicalTape;
132132

133133
/*
@@ -156,7 +156,7 @@ struct LogicalTapeSet
156156
* is of length nTapes.
157157
*/
158158
int nTapes; /* # of logical tapes in set */
159-
LogicalTape *tapes[1]; /* must be last in struct! */
159+
LogicalTape tapes[1]; /* must be last in struct! */
160160
};
161161

162162
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer);
@@ -327,6 +327,10 @@ ltsRewindIndirectBlock(LogicalTapeSet *lts,
327327
IndirectBlock *indirect,
328328
bool freezing)
329329
{
330+
/* Handle case of never-written-to tape */
331+
if (indirect == NULL)
332+
return -1L;
333+
330334
/* Insert sentinel if block is not full */
331335
if (indirect->nextSlot < BLOCKS_PER_INDIR_BLOCK)
332336
indirect->ptrs[indirect->nextSlot] = -1L;
@@ -366,6 +370,10 @@ static long
366370
ltsRewindFrozenIndirectBlock(LogicalTapeSet *lts,
367371
IndirectBlock *indirect)
368372
{
373+
/* Handle case of never-written-to tape */
374+
if (indirect == NULL)
375+
return -1L;
376+
369377
/*
370378
* If block is not topmost, recurse to obtain address of first block in
371379
* this hierarchy level. Read that one in.
@@ -399,6 +407,10 @@ ltsRecallNextBlockNum(LogicalTapeSet *lts,
399407
IndirectBlock *indirect,
400408
bool frozen)
401409
{
410+
/* Handle case of never-written-to tape */
411+
if (indirect == NULL)
412+
return -1L;
413+
402414
if (indirect->nextSlot >= BLOCKS_PER_INDIR_BLOCK ||
403415
indirect->ptrs[indirect->nextSlot] == -1L)
404416
{
@@ -432,6 +444,10 @@ static long
432444
ltsRecallPrevBlockNum(LogicalTapeSet *lts,
433445
IndirectBlock *indirect)
434446
{
447+
/* Handle case of never-written-to tape */
448+
if (indirect == NULL)
449+
return -1L;
450+
435451
if (indirect->nextSlot <= 1)
436452
{
437453
long indirblock;
@@ -467,12 +483,12 @@ LogicalTapeSetCreate(int ntapes)
467483
int i;
468484

469485
/*
470-
* Create top-level struct. First LogicalTape pointer is already counted
471-
* in sizeof(LogicalTapeSet).
486+
* Create top-level struct including per-tape LogicalTape structs.
487+
* First LogicalTape struct is already counted in sizeof(LogicalTapeSet).
472488
*/
473489
Assert(ntapes > 0);
474490
lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet) +
475-
(ntapes - 1) *sizeof(LogicalTape *));
491+
(ntapes - 1) * sizeof(LogicalTape));
476492
lts->pfile = BufFileCreateTemp(false);
477493
lts->nFileBlocks = 0L;
478494
lts->freeBlocksLen = 32; /* reasonable initial guess */
@@ -481,20 +497,21 @@ LogicalTapeSetCreate(int ntapes)
481497
lts->nTapes = ntapes;
482498

483499
/*
484-
* Create per-tape structs, including first-level indirect blocks.
500+
* Initialize per-tape structs. Note we allocate the I/O buffer and
501+
* first-level indirect block for a tape only when it is first actually
502+
* written to. This avoids wasting memory space when tuplesort.c
503+
* overestimates the number of tapes needed.
485504
*/
486505
for (i = 0; i < ntapes; i++)
487506
{
488-
lt = (LogicalTape *) palloc(sizeof(LogicalTape));
489-
lts->tapes[i] = lt;
490-
lt->indirect = (IndirectBlock *) palloc(sizeof(IndirectBlock));
491-
lt->indirect->nextSlot = 0;
492-
lt->indirect->nextup = NULL;
507+
lt = &lts->tapes[i];
508+
lt->indirect = NULL;
493509
lt->writing = true;
494510
lt->frozen = false;
495511
lt->dirty = false;
496512
lt->numFullBlocks = 0L;
497513
lt->lastBlockBytes = 0;
514+
lt->buffer = NULL;
498515
lt->curBlockNumber = 0L;
499516
lt->pos = 0;
500517
lt->nbytes = 0;
@@ -516,13 +533,14 @@ LogicalTapeSetClose(LogicalTapeSet *lts)
516533
BufFileClose(lts->pfile);
517534
for (i = 0; i < lts->nTapes; i++)
518535
{
519-
lt = lts->tapes[i];
536+
lt = &lts->tapes[i];
520537
for (ib = lt->indirect; ib != NULL; ib = nextib)
521538
{
522539
nextib = ib->nextup;
523540
pfree(ib);
524541
}
525-
pfree(lt);
542+
if (lt->buffer)
543+
pfree(lt->buffer);
526544
}
527545
pfree(lts->freeBlocks);
528546
pfree(lts);
@@ -556,9 +574,19 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
556574
size_t nthistime;
557575

558576
Assert(tapenum >= 0 && tapenum < lts->nTapes);
559-
lt = lts->tapes[tapenum];
577+
lt = &lts->tapes[tapenum];
560578
Assert(lt->writing);
561579

580+
/* Allocate data buffer and first indirect block on first write */
581+
if (lt->buffer == NULL)
582+
lt->buffer = (char *) palloc(BLCKSZ);
583+
if (lt->indirect == NULL)
584+
{
585+
lt->indirect = (IndirectBlock *) palloc(sizeof(IndirectBlock));
586+
lt->indirect->nextSlot = 0;
587+
lt->indirect->nextup = NULL;
588+
}
589+
562590
while (size > 0)
563591
{
564592
if (lt->pos >= BLCKSZ)
@@ -606,7 +634,7 @@ LogicalTapeRewind(LogicalTapeSet *lts, int tapenum, bool forWrite)
606634
long datablocknum;
607635

608636
Assert(tapenum >= 0 && tapenum < lts->nTapes);
609-
lt = lts->tapes[tapenum];
637+
lt = &lts->tapes[tapenum];
610638

611639
if (!forWrite)
612640
{
@@ -660,13 +688,16 @@ LogicalTapeRewind(LogicalTapeSet *lts, int tapenum, bool forWrite)
660688

661689
Assert(!lt->writing && !lt->frozen);
662690
/* Must truncate the indirect-block hierarchy down to one level. */
663-
for (ib = lt->indirect->nextup; ib != NULL; ib = nextib)
691+
if (lt->indirect)
664692
{
665-
nextib = ib->nextup;
666-
pfree(ib);
693+
for (ib = lt->indirect->nextup; ib != NULL; ib = nextib)
694+
{
695+
nextib = ib->nextup;
696+
pfree(ib);
697+
}
698+
lt->indirect->nextSlot = 0;
699+
lt->indirect->nextup = NULL;
667700
}
668-
lt->indirect->nextSlot = 0;
669-
lt->indirect->nextup = NULL;
670701
lt->writing = true;
671702
lt->dirty = false;
672703
lt->numFullBlocks = 0L;
@@ -691,7 +722,7 @@ LogicalTapeRead(LogicalTapeSet *lts, int tapenum,
691722
size_t nthistime;
692723

693724
Assert(tapenum >= 0 && tapenum < lts->nTapes);
694-
lt = lts->tapes[tapenum];
725+
lt = &lts->tapes[tapenum];
695726
Assert(!lt->writing);
696727

697728
while (size > 0)
@@ -749,7 +780,7 @@ LogicalTapeFreeze(LogicalTapeSet *lts, int tapenum)
749780
long datablocknum;
750781

751782
Assert(tapenum >= 0 && tapenum < lts->nTapes);
752-
lt = lts->tapes[tapenum];
783+
lt = &lts->tapes[tapenum];
753784
Assert(lt->writing);
754785

755786
/*
@@ -793,7 +824,7 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
793824
int newpos;
794825

795826
Assert(tapenum >= 0 && tapenum < lts->nTapes);
796-
lt = lts->tapes[tapenum];
827+
lt = &lts->tapes[tapenum];
797828
Assert(lt->frozen);
798829

799830
/*
@@ -858,7 +889,7 @@ LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
858889
LogicalTape *lt;
859890

860891
Assert(tapenum >= 0 && tapenum < lts->nTapes);
861-
lt = lts->tapes[tapenum];
892+
lt = &lts->tapes[tapenum];
862893
Assert(lt->frozen);
863894
Assert(offset >= 0 && offset <= BLCKSZ);
864895

@@ -921,7 +952,7 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
921952
LogicalTape *lt;
922953

923954
Assert(tapenum >= 0 && tapenum < lts->nTapes);
924-
lt = lts->tapes[tapenum];
955+
lt = &lts->tapes[tapenum];
925956
*blocknum = lt->curBlockNumber;
926957
*offset = lt->pos;
927958
}

0 commit comments

Comments
 (0)