From: Tom Lane Date: Tue, 28 Oct 2008 15:51:03 +0000 (+0000) Subject: Arrange to squeeze out the MINIMAL_TUPLE_PADDING in the tuple representation X-Git-Tag: REL8_4_BETA1~811 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d26bf23f344887aecac93e9cd22b1dae64f18c83;p=postgresql Arrange to squeeze out the MINIMAL_TUPLE_PADDING in the tuple representation written to temp files by tuplesort.c and tuplestore.c. This saves 2 bytes per row for 32-bit machines, and 6 bytes per row for 64-bit machines, which seems worth the slight additional uglification of the tuple read/write routines. --- diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 29a076e138..02aee0f8b4 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -91,7 +91,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.87 2008/09/15 18:43:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.88 2008/10/28 15:51:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2632,18 +2632,20 @@ copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup) &stup->isnull1); } -/* - * Since MinimalTuple already has length in its first word, we don't need - * to write that separately. - */ static void writetup_heap(Tuplesortstate *state, int tapenum, SortTuple *stup) { MinimalTuple tuple = (MinimalTuple) stup->tuple; - unsigned int tuplen = tuple->t_len; + /* the part of the MinimalTuple we'll write: */ + char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET; + unsigned int tupbodylen = tuple->t_len - MINIMAL_TUPLE_DATA_OFFSET; + /* total on-disk footprint: */ + unsigned int tuplen = tupbodylen + sizeof(int); LogicalTapeWrite(state->tapeset, tapenum, - (void *) tuple, tuplen); + (void *) &tuplen, sizeof(tuplen)); + LogicalTapeWrite(state->tapeset, tapenum, + (void *) tupbody, tupbodylen); if (state->randomAccess) /* need trailing length word? */ LogicalTapeWrite(state->tapeset, tapenum, (void *) &tuplen, sizeof(tuplen)); @@ -2656,16 +2658,18 @@ static void readtup_heap(Tuplesortstate *state, SortTuple *stup, int tapenum, unsigned int len) { - MinimalTuple tuple = (MinimalTuple) palloc(len); - unsigned int tuplen; + unsigned int tupbodylen = len - sizeof(int); + unsigned int tuplen = tupbodylen + MINIMAL_TUPLE_DATA_OFFSET; + MinimalTuple tuple = (MinimalTuple) palloc(tuplen); + char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET; HeapTupleData htup; USEMEM(state, GetMemoryChunkSpace(tuple)); /* read in the tuple proper */ - tuple->t_len = len; + tuple->t_len = tuplen; if (LogicalTapeRead(state->tapeset, tapenum, - (void *) ((char *) tuple + sizeof(int)), - len - sizeof(int)) != (size_t) (len - sizeof(int))) + (void *) tupbody, + tupbodylen) != (size_t) tupbodylen) elog(ERROR, "unexpected end of data"); if (state->randomAccess) /* need trailing length word? */ if (LogicalTapeRead(state->tapeset, tapenum, (void *) &tuplen, diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index b5bd67c1b4..a99386fa93 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -46,7 +46,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.42 2008/10/07 00:05:55 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.43 2008/10/28 15:51:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1173,9 +1173,17 @@ static void writetup_heap(Tuplestorestate *state, void *tup) { MinimalTuple tuple = (MinimalTuple) tup; - unsigned int tuplen = tuple->t_len; - - if (BufFileWrite(state->myfile, (void *) tuple, tuplen) != (size_t) tuplen) + /* the part of the MinimalTuple we'll write: */ + char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET; + unsigned int tupbodylen = tuple->t_len - MINIMAL_TUPLE_DATA_OFFSET; + /* total on-disk footprint: */ + unsigned int tuplen = tupbodylen + sizeof(int); + + if (BufFileWrite(state->myfile, (void *) &tuplen, + sizeof(tuplen)) != sizeof(tuplen)) + elog(ERROR, "write failed"); + if (BufFileWrite(state->myfile, (void *) tupbody, + tupbodylen) != (size_t) tupbodylen) elog(ERROR, "write failed"); if (state->backward) /* need trailing length word? */ if (BufFileWrite(state->myfile, (void *) &tuplen, @@ -1189,14 +1197,16 @@ writetup_heap(Tuplestorestate *state, void *tup) static void * readtup_heap(Tuplestorestate *state, unsigned int len) { - MinimalTuple tuple = (MinimalTuple) palloc(len); - unsigned int tuplen; + unsigned int tupbodylen = len - sizeof(int); + unsigned int tuplen = tupbodylen + MINIMAL_TUPLE_DATA_OFFSET; + MinimalTuple tuple = (MinimalTuple) palloc(tuplen); + char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET; USEMEM(state, GetMemoryChunkSpace(tuple)); /* read in the tuple proper */ - tuple->t_len = len; - if (BufFileRead(state->myfile, (void *) ((char *) tuple + sizeof(int)), - len - sizeof(int)) != (size_t) (len - sizeof(int))) + tuple->t_len = tuplen; + if (BufFileRead(state->myfile, (void *) tupbody, + tupbodylen) != (size_t) tupbodylen) elog(ERROR, "unexpected end of data"); if (state->backward) /* need trailing length word? */ if (BufFileRead(state->myfile, (void *) &tuplen, diff --git a/src/include/access/htup.h b/src/include/access/htup.h index 85271c26c3..0803c1b2c7 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.101 2008/08/11 11:05:11 heikki Exp $ + * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.102 2008/10/28 15:51:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -420,11 +420,17 @@ do { \ * * Note that t_hoff is computed the same as in a full tuple, hence it includes * the MINIMAL_TUPLE_OFFSET distance. t_len does not include that, however. + * + * MINIMAL_TUPLE_DATA_OFFSET is the offset to the first useful (non-pad) data + * other than the length word. tuplesort.c and tuplestore.c use this to avoid + * writing the padding to disk. */ #define MINIMAL_TUPLE_OFFSET \ ((offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) / MAXIMUM_ALIGNOF * MAXIMUM_ALIGNOF) #define MINIMAL_TUPLE_PADDING \ ((offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) % MAXIMUM_ALIGNOF) +#define MINIMAL_TUPLE_DATA_OFFSET \ + offsetof(MinimalTupleData, t_infomask2) typedef struct MinimalTupleData {