Commit 8ef30756 authored by marko's avatar marko

branches/zip: Speed up rec_offs_any_extern() and rec_offs_n_extern()

by adding the REC_OFFS_EXTERNAL flag to rec_offs_base(offsets)[0].

This reduces the processor usage of page_zip_write_rec() by about 40%
in one test case.  The code could be sped up further by testing
rec_offs_any_extern() outside of loops that check rec_offs_nth_extern().
The vast majority of records does not contain any externally stored columns.
parent 645b3922
......@@ -420,6 +420,15 @@ rec_offs_comp(
/* out: nonzero if compact format */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**********************************************************
Determine if the offsets are for a record containing
externally stored columns. */
UNIV_INLINE
ulint
rec_offs_any_extern(
/*================*/
/* out: nonzero if externally stored */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**********************************************************
Returns nonzero if the extern bit is set in nth field of rec. */
UNIV_INLINE
ulint
......@@ -448,15 +457,6 @@ rec_offs_nth_size(
ulint n); /* in: nth field */
/**********************************************************
Returns TRUE if the extern bit is set in any of the fields
of a record. */
UNIV_INLINE
ibool
rec_offs_any_extern(
/*================*/
/* out: TRUE if a field is stored externally */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**********************************************************
Returns the number of extern bits set in a record. */
UNIV_INLINE
ulint
......
......@@ -1045,6 +1045,20 @@ rec_offs_comp(
return(*rec_offs_base(offsets) & REC_OFFS_COMPACT);
}
/**********************************************************
Determine if the offsets are for a record containing
externally stored columns. */
UNIV_INLINE
ulint
rec_offs_any_extern(
/*================*/
/* out: nonzero if externally stored */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ut_ad(rec_offs_validate(NULL, NULL, offsets));
return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL));
}
/**********************************************************
Returns nonzero if the extern bit is set in nth field of rec. */
UNIV_INLINE
......@@ -1093,25 +1107,6 @@ rec_offs_nth_size(
& REC_OFFS_MASK);
}
/**********************************************************
Returns TRUE if the extern bit is set in any of the fields
of a record. */
UNIV_INLINE
ibool
rec_offs_any_extern(
/*================*/
/* out: TRUE if a field is stored externally */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint i;
for (i = rec_offs_n_fields(offsets); i--; ) {
if (rec_offs_nth_extern(offsets, i)) {
return(TRUE);
}
}
return(FALSE);
}
/**********************************************************
Returns the number of extern bits set in a record. */
UNIV_INLINE
......@@ -1121,13 +1116,18 @@ rec_offs_n_extern(
/* out: number of externally stored fields */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint i;
ulint n = 0;
for (i = rec_offs_n_fields(offsets); i--; ) {
if (rec_offs_nth_extern(offsets, i)) {
n++;
if (rec_offs_any_extern(offsets)) {
ulint i;
for (i = rec_offs_n_fields(offsets); i--; ) {
if (rec_offs_nth_extern(offsets, i)) {
n++;
}
}
}
return(n);
}
......@@ -1416,7 +1416,7 @@ rec_offs_extra_size(
{
ulint size;
ut_ad(rec_offs_validate(NULL, NULL, offsets));
size = *rec_offs_base(offsets) & ~REC_OFFS_COMPACT;
size = *rec_offs_base(offsets) & ~(REC_OFFS_COMPACT | REC_OFFS_EXTERNAL);
ut_ad(size < UNIV_PAGE_SIZE);
return(size);
}
......
......@@ -2200,6 +2200,9 @@ page_zip_decompress_clust(
columns in this record. For each externally
stored column, restore or clear the
BTR_EXTERN_FIELD_REF. */
if (!rec_offs_any_extern(offsets)) {
continue;
}
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
if (!rec_offs_nth_extern(offsets, i)) {
......@@ -3159,16 +3162,20 @@ page_zip_clear_rec(
/* Do not clear the record, because there is not enough space
to log the operation. */
ulint i;
for (i = rec_offs_n_fields(offsets); i--; ) {
/* Clear all BLOB pointers in order to make
page_zip_validate() pass. */
if (rec_offs_nth_extern(offsets, i)) {
ulint len;
byte* field = rec_get_nth_field(rec, offsets,
i, &len);
memset(field + len - BTR_EXTERN_FIELD_REF_SIZE,
0, BTR_EXTERN_FIELD_REF_SIZE);
if (rec_offs_any_extern(offsets)) {
ulint i;
for (i = rec_offs_n_fields(offsets); i--; ) {
/* Clear all BLOB pointers in order to make
page_zip_validate() pass. */
if (rec_offs_nth_extern(offsets, i)) {
ulint len;
byte* field = rec_get_nth_field(
rec, offsets, i, &len);
memset(field + len
- BTR_EXTERN_FIELD_REF_SIZE,
0, BTR_EXTERN_FIELD_REF_SIZE);
}
}
}
}
......
......@@ -218,7 +218,8 @@ ulint, where rec_offs_n_fields(offsets) has been initialized to the
number of fields in the record. The rest of the array will be
initialized by this function. rec_offs_base(offsets)[0] will be set
to the extra size (if REC_OFFS_COMPACT is set, the record is in the
new format), and rec_offs_base(offsets)[1..n_fields] will be set to
new format; if REC_OFFS_EXTERNAL is set, the record contains externally
stored columns), and rec_offs_base(offsets)[1..n_fields] will be set to
offsets past the end of fields 0..n_fields, or to the beginning of
fields 1..n_fields+1. When the high-order bit of the offset at [i+1]
is set (REC_OFFS_SQL_NULL), the field i is NULL. When the second
......@@ -240,6 +241,7 @@ rec_init_offsets(
rec_offs_make_valid(rec, index, offsets);
if (dict_table_is_comp(index->table)) {
ulint any_ext;
const byte* nulls;
const byte* lens;
dict_field_t* field;
......@@ -266,6 +268,7 @@ rec_init_offsets(
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
lens = nulls - (index->n_nullable + 7) / 8;
offs = 0;
any_ext = 0;
null_mask = 1;
/* read the lengths of fields 0..n */
......@@ -316,6 +319,7 @@ rec_init_offsets(
& 0x4000)) {
ut_ad(dict_index_is_clust
(index));
any_ext = REC_OFFS_EXTERNAL;
len = offs
| REC_OFFS_EXTERNAL;
} else {
......@@ -335,7 +339,7 @@ rec_init_offsets(
} while (++i < rec_offs_n_fields(offsets));
*rec_offs_base(offsets)
= (rec - (lens + 1)) | REC_OFFS_COMPACT;
= (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
} else {
/* Old-style record: determine extra size and end offsets */
offs = REC_N_OLD_EXTRA_BYTES;
......@@ -364,6 +368,7 @@ rec_init_offsets(
if (offs & REC_2BYTE_EXTERN_MASK) {
offs &= ~REC_2BYTE_EXTERN_MASK;
offs |= REC_OFFS_EXTERNAL;
*rec_offs_base(offsets) |= REC_OFFS_EXTERNAL;
}
rec_offs_base(offsets)[1 + i] = offs;
} while (++i < rec_offs_n_fields(offsets));
......@@ -459,6 +464,7 @@ rec_get_offsets_reverse(
ulint n;
ulint i;
ulint offs;
ulint any_ext;
const byte* nulls;
const byte* lens;
dict_field_t* field;
......@@ -485,6 +491,7 @@ rec_get_offsets_reverse(
lens = nulls + (index->n_nullable + 7) / 8;
i = offs = 0;
null_mask = 1;
any_ext = 0;
/* read the lengths of fields 0..n */
do {
......@@ -529,6 +536,7 @@ rec_get_offsets_reverse(
offs += len & 0x3fff;
if (UNIV_UNLIKELY(len & 0x4000)) {
any_ext = REC_OFFS_EXTERNAL;
len = offs | REC_OFFS_EXTERNAL;
} else {
len = offs;
......@@ -548,7 +556,7 @@ rec_get_offsets_reverse(
ut_ad(lens >= extra);
*rec_offs_base(offsets) = (lens - extra + REC_N_NEW_EXTRA_BYTES)
| REC_OFFS_COMPACT;
| REC_OFFS_COMPACT | any_ext;
}
/****************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment