Skip to content

Commit

Permalink
enhancing-copy-thoughput
Browse files Browse the repository at this point in the history
  • Loading branch information
naanagon committed Apr 11, 2024
1 parent 1fda770 commit 59af390
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 2 deletions.
211 changes: 211 additions & 0 deletions src/postgres/src/backend/access/common/heaptuple.c
Expand Up @@ -657,6 +657,217 @@ nocachegetattr(HeapTuple tuple,
return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
}

/*
This method is exactly same as nocachegetattr
but in case of case3: an offset array is built and
that is used before traversing over all the attributes.
*/
Datum
nocachegetattr_with_offsets(HeapTuple tuple,
int attnum,
TupleDesc tupleDesc,
int* offsets)
{
HeapTupleHeader tup = tuple->t_data;
char *tp; /* ptr to data part of tuple */
bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
bool slow = false; /* do we have to walk attrs? */
int off; /* current offset within data */

/* ----------------
* Three cases:
*
* 1: No nulls and no variable-width attributes.
* 2: Has a null or a var-width AFTER att.
* 3: Has nulls or var-widths BEFORE att.
* ----------------
*/

attnum--;

if (!HeapTupleNoNulls(tuple))
{
/*
* there's a null somewhere in the tuple
*
* check to see if any preceding bits are null...
*/
int byte = attnum >> 3;
int finalbit = attnum & 0x07;

/* check for nulls "before" final bit of last byte */
if ((~bp[byte]) & ((1 << finalbit) - 1))
slow = true;
else
{
/* check for nulls in any "earlier" bytes */
int i;

for (i = 0; i < byte; i++)
{
if (bp[i] != 0xFF)
{
slow = true;
break;
}
}
}
}

tp = (char *) tup + tup->t_hoff;

if (!slow)
{
Form_pg_attribute att;

/*
* If we get here, there are no nulls up to and including the target
* attribute. If we have a cached offset, we can use it.
*/
att = TupleDescAttr(tupleDesc, attnum);
if (att->attcacheoff >= 0)
return fetchatt(att, tp + att->attcacheoff);

/*
* Otherwise, check for non-fixed-length attrs up to and including
* target. If there aren't any, it's safe to cheaply initialize the
* cached offsets for these attrs.
*/
if (HeapTupleHasVarWidth(tuple))
{
int j;

for (j = 0; j <= attnum; j++)
{
if (TupleDescAttr(tupleDesc, j)->attlen <= 0)
{
slow = true;
break;
}
}
}
}

if (!slow)
{
int natts = tupleDesc->natts;
int j = 1;

/*
* If we get here, we have a tuple with no nulls or var-widths up to
* and including the target attribute, so we can use the cached offset
* ... only we don't have it yet, or we'd not have got here. Since
* it's cheap to compute offsets for fixed-width columns, we take the
* opportunity to initialize the cached offsets for *all* the leading
* fixed-width columns, in hope of avoiding future visits to this
* routine.
*/
TupleDescAttr(tupleDesc, 0)->attcacheoff = 0;

/* we might have set some offsets in the slow path previously */
while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0)
j++;

off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff +
TupleDescAttr(tupleDesc, j - 1)->attlen;

for (; j < natts; j++)
{
Form_pg_attribute att = TupleDescAttr(tupleDesc, j);

if (att->attlen <= 0)
break;

off = att_align_nominal(off, att->attalign);

att->attcacheoff = off;

off += att->attlen;
}

Assert(j > attnum);

off = TupleDescAttr(tupleDesc, attnum)->attcacheoff;
}
else
{
if(offsets[attnum]!=-1){
off=offsets[attnum];
return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
}

bool usecache = true;
int i;
int natts = tupleDesc->natts-1;
/*
* Now we know that we have to walk the tuple CAREFULLY. But we still
* might be able to cache some offsets for next time.
*
* Note - This loop is a little tricky. For each non-null attribute,
* we have to first account for alignment padding before the attr,
* then advance over the attr based on its length. Nulls have no
* storage and no alignment padding either. We can use/set
* attcacheoff until we reach either a null or a var-width attribute.
*/
off = 0;
for (i = 0;; i++) /* loop exit is at "break" */
{
Form_pg_attribute att = TupleDescAttr(tupleDesc, i);

if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
{
usecache = false;
if (i == natts) /* this can be the target att as we are iterating over natts*/
break;
}

/* If we know the next offset, we can skip the rest */
if (usecache && att->attcacheoff >= 0)
off = att->attcacheoff;
else if (att->attlen == -1)
{
/*
* We can only cache the offset for a varlena attribute if the
* offset is already suitably aligned, so that there would be
* no pad bytes in any case: then the offset will be valid for
* either an aligned or unaligned value.
*/
if (usecache &&
off == att_align_nominal(off, att->attalign))
att->attcacheoff = off;
else
{
off = att_align_pointer(off, att->attalign, -1,
tp + off);
usecache = false;
}
}
else
{
/* not varlena, so safe to use att_align_nominal */
off = att_align_nominal(off, att->attalign);

if (usecache)
att->attcacheoff = off;
}
/* offsets array is populated here*/
offsets[i]=off;
if (i == natts)
break;

off = att_addlength_pointer(off, att->attlen, tp + off);

if (usecache && att->attlen <= 0)
usecache = false;
}
if(offsets[attnum]!=-1){
off=offsets[attnum];
return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
}
}

return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
}
/* ----------------
* heap_getsysattr
*
Expand Down
8 changes: 6 additions & 2 deletions src/postgres/src/backend/executor/ybcModifyTable.c
Expand Up @@ -293,6 +293,9 @@ static Oid YBCApplyInsertRow(
YBCBindColumn columns[buf_size];
YBCBindColumn* column = columns;

int* offsets=malloc(natts*sizeof(int));
for(int i=0;i<natts;i++)
offsets[i]=-1;
for (AttrNumber attnum = minattr; attnum <= natts; attnum++)
{
/* Skip virtual (system) and dropped columns */
Expand Down Expand Up @@ -323,13 +326,14 @@ static Oid YBCApplyInsertRow(
*/
Oid collation_id = YBEncodingCollation(insert_stmt, attnum,
ybc_get_attcollation(RelationGetDescr(rel), attnum));
column->datum = heap_getattr(tuple, attnum, tupleDesc, &column->is_null);
column->datum = heap_getattr_with_offsets(tuple, attnum, tupleDesc, &column->is_null, offsets);
YBGetCollationInfo(collation_id, column->type_entity, column->datum, column->is_null, &column->collation_info);

/* Add the column value to the insert request */
++column;
}

free(offsets);
offsets=NULL;
HandleYBStatus(YBCPgDmlBindRow(insert_stmt, tuple->t_ybctid, columns, column - columns));

/*
Expand Down
49 changes: 49 additions & 0 deletions src/postgres/src/include/access/htup_details.h
Expand Up @@ -766,6 +766,41 @@ extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
#endif /* defined(DISABLE_COMPLEX_MACRO) */


#if !defined(DISABLE_COMPLEX_MACRO)

#define fastgetattr_with_offsets(tup, attnum, tupleDesc, isnull, offsets) \
( \
AssertMacro((attnum) > 0), \
(*(isnull) = false), \
HeapTupleNoNulls(tup) ? \
( \
TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff >= 0 ? \
( \
fetchatt(TupleDescAttr((tupleDesc), (attnum)-1), \
(char *) (tup)->t_data + (tup)->t_data->t_hoff + \
TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff)\
) \
: \
nocachegetattr_with_offsets((tup), (attnum), (tupleDesc), (offsets)) \
) \
: \
( \
att_isnull((attnum)-1, (tup)->t_data->t_bits) ? \
( \
(*(isnull) = true), \
(Datum)NULL \
) \
: \
( \
nocachegetattr_with_offsets((tup), (attnum), (tupleDesc), (offsets)) \
) \
) \
)
#else /* defined(DISABLE_COMPLEX_MACRO) */

extern Datum fastgetattr_with_offsets(HeapTuple tup, int attnum, TupleDesc tupleDesc,
bool *isnull, int* offsets);
#endif
/* ----------------
* heap_getattr
*
Expand Down Expand Up @@ -794,6 +829,18 @@ extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
heap_getsysattr((tup), (attnum), (tupleDesc), (isnull)) \
)

#define heap_getattr_with_offsets(tup, attnum, tupleDesc, isnull, offsets) \
( \
((attnum) > 0) ? \
( \
((attnum) > (int) HeapTupleHeaderGetNatts((tup)->t_data)) ? \
getmissingattr((tupleDesc), (attnum), (isnull)) \
: \
fastgetattr_with_offsets((tup), (attnum), (tupleDesc), (isnull), (offsets)) \
) \
: \
heap_getsysattr((tup), (attnum), (tupleDesc), (isnull)) \
)

/* prototypes for functions in common/heaptuple.c */
extern Size heap_compute_data_size(TupleDesc tupleDesc,
Expand All @@ -805,6 +852,8 @@ extern void heap_fill_tuple(TupleDesc tupleDesc,
extern bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc);
extern Datum nocachegetattr(HeapTuple tup, int attnum,
TupleDesc att);
extern Datum nocachegetattr_with_offsets(HeapTuple tup, int attnum,
TupleDesc att, int* offsets);
extern Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
bool *isnull);
extern Datum getmissingattr(TupleDesc tupleDesc,
Expand Down

0 comments on commit 59af390

Please sign in to comment.