Arrange to squeeze out the MINIMAL_TUPLE_PADDING in the tuple representation
authorTom Lane
Tue, 28 Oct 2008 15:51:03 +0000 (15:51 +0000)
committerTom Lane
Tue, 28 Oct 2008 15:51:03 +0000 (15:51 +0000)
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.

src/backend/utils/sort/tuplesort.c
src/backend/utils/sort/tuplestore.c
src/include/access/htup.h

index 29a076e1384624bf97664505d83b10996a264aa7..02aee0f8b405c48a2c20777964dc844ec0df5e5d 100644 (file)
@@ -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,
index b5bd67c1b4e6fa870154246749ee576809479f12..a99386fa936770937943b80c3f3def056861e88a 100644 (file)
@@ -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,
index 85271c26c3ac80bf941cefc0d338826fc78fa19c..0803c1b2c77cbd587245809f989963b0ae0c8b49 100644 (file)
@@ -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
 {