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( ...@@ -420,6 +420,15 @@ rec_offs_comp(
/* out: nonzero if compact format */ /* out: nonzero if compact format */
const ulint* offsets);/* in: array returned by rec_get_offsets() */ 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. */ Returns nonzero if the extern bit is set in nth field of rec. */
UNIV_INLINE UNIV_INLINE
ulint ulint
...@@ -448,15 +457,6 @@ rec_offs_nth_size( ...@@ -448,15 +457,6 @@ rec_offs_nth_size(
ulint n); /* in: nth field */ 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. */ Returns the number of extern bits set in a record. */
UNIV_INLINE UNIV_INLINE
ulint ulint
......
...@@ -1045,6 +1045,20 @@ rec_offs_comp( ...@@ -1045,6 +1045,20 @@ rec_offs_comp(
return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); 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. */ Returns nonzero if the extern bit is set in nth field of rec. */
UNIV_INLINE UNIV_INLINE
...@@ -1093,25 +1107,6 @@ rec_offs_nth_size( ...@@ -1093,25 +1107,6 @@ rec_offs_nth_size(
& REC_OFFS_MASK); & 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. */ Returns the number of extern bits set in a record. */
UNIV_INLINE UNIV_INLINE
...@@ -1121,13 +1116,18 @@ rec_offs_n_extern( ...@@ -1121,13 +1116,18 @@ rec_offs_n_extern(
/* out: number of externally stored fields */ /* out: number of externally stored fields */
const ulint* offsets)/* in: array returned by rec_get_offsets() */ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{ {
ulint i;
ulint n = 0; ulint n = 0;
if (rec_offs_any_extern(offsets)) {
ulint i;
for (i = rec_offs_n_fields(offsets); i--; ) { for (i = rec_offs_n_fields(offsets); i--; ) {
if (rec_offs_nth_extern(offsets, i)) { if (rec_offs_nth_extern(offsets, i)) {
n++; n++;
} }
} }
}
return(n); return(n);
} }
...@@ -1416,7 +1416,7 @@ rec_offs_extra_size( ...@@ -1416,7 +1416,7 @@ rec_offs_extra_size(
{ {
ulint size; ulint size;
ut_ad(rec_offs_validate(NULL, NULL, offsets)); 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); ut_ad(size < UNIV_PAGE_SIZE);
return(size); return(size);
} }
......
...@@ -2200,6 +2200,9 @@ page_zip_decompress_clust( ...@@ -2200,6 +2200,9 @@ page_zip_decompress_clust(
columns in this record. For each externally columns in this record. For each externally
stored column, restore or clear the stored column, restore or clear the
BTR_EXTERN_FIELD_REF. */ BTR_EXTERN_FIELD_REF. */
if (!rec_offs_any_extern(offsets)) {
continue;
}
for (i = 0; i < rec_offs_n_fields(offsets); i++) { for (i = 0; i < rec_offs_n_fields(offsets); i++) {
if (!rec_offs_nth_extern(offsets, i)) { if (!rec_offs_nth_extern(offsets, i)) {
...@@ -3159,19 +3162,23 @@ page_zip_clear_rec( ...@@ -3159,19 +3162,23 @@ page_zip_clear_rec(
/* Do not clear the record, because there is not enough space /* Do not clear the record, because there is not enough space
to log the operation. */ to log the operation. */
if (rec_offs_any_extern(offsets)) {
ulint i; ulint i;
for (i = rec_offs_n_fields(offsets); i--; ) { for (i = rec_offs_n_fields(offsets); i--; ) {
/* Clear all BLOB pointers in order to make /* Clear all BLOB pointers in order to make
page_zip_validate() pass. */ page_zip_validate() pass. */
if (rec_offs_nth_extern(offsets, i)) { if (rec_offs_nth_extern(offsets, i)) {
ulint len; ulint len;
byte* field = rec_get_nth_field(rec, offsets, byte* field = rec_get_nth_field(
i, &len); rec, offsets, i, &len);
memset(field + len - BTR_EXTERN_FIELD_REF_SIZE, memset(field + len
- BTR_EXTERN_FIELD_REF_SIZE,
0, BTR_EXTERN_FIELD_REF_SIZE); 0, BTR_EXTERN_FIELD_REF_SIZE);
} }
} }
} }
}
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(page_zip, page)); ut_a(page_zip_validate(page_zip, page));
......
...@@ -218,7 +218,8 @@ ulint, where rec_offs_n_fields(offsets) has been initialized to the ...@@ -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 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 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 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 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] 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 is set (REC_OFFS_SQL_NULL), the field i is NULL. When the second
...@@ -240,6 +241,7 @@ rec_init_offsets( ...@@ -240,6 +241,7 @@ rec_init_offsets(
rec_offs_make_valid(rec, index, offsets); rec_offs_make_valid(rec, index, offsets);
if (dict_table_is_comp(index->table)) { if (dict_table_is_comp(index->table)) {
ulint any_ext;
const byte* nulls; const byte* nulls;
const byte* lens; const byte* lens;
dict_field_t* field; dict_field_t* field;
...@@ -266,6 +268,7 @@ rec_init_offsets( ...@@ -266,6 +268,7 @@ rec_init_offsets(
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
lens = nulls - (index->n_nullable + 7) / 8; lens = nulls - (index->n_nullable + 7) / 8;
offs = 0; offs = 0;
any_ext = 0;
null_mask = 1; null_mask = 1;
/* read the lengths of fields 0..n */ /* read the lengths of fields 0..n */
...@@ -316,6 +319,7 @@ rec_init_offsets( ...@@ -316,6 +319,7 @@ rec_init_offsets(
& 0x4000)) { & 0x4000)) {
ut_ad(dict_index_is_clust ut_ad(dict_index_is_clust
(index)); (index));
any_ext = REC_OFFS_EXTERNAL;
len = offs len = offs
| REC_OFFS_EXTERNAL; | REC_OFFS_EXTERNAL;
} else { } else {
...@@ -335,7 +339,7 @@ rec_init_offsets( ...@@ -335,7 +339,7 @@ rec_init_offsets(
} while (++i < rec_offs_n_fields(offsets)); } while (++i < rec_offs_n_fields(offsets));
*rec_offs_base(offsets) *rec_offs_base(offsets)
= (rec - (lens + 1)) | REC_OFFS_COMPACT; = (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
} else { } else {
/* Old-style record: determine extra size and end offsets */ /* Old-style record: determine extra size and end offsets */
offs = REC_N_OLD_EXTRA_BYTES; offs = REC_N_OLD_EXTRA_BYTES;
...@@ -364,6 +368,7 @@ rec_init_offsets( ...@@ -364,6 +368,7 @@ rec_init_offsets(
if (offs & REC_2BYTE_EXTERN_MASK) { if (offs & REC_2BYTE_EXTERN_MASK) {
offs &= ~REC_2BYTE_EXTERN_MASK; offs &= ~REC_2BYTE_EXTERN_MASK;
offs |= REC_OFFS_EXTERNAL; offs |= REC_OFFS_EXTERNAL;
*rec_offs_base(offsets) |= REC_OFFS_EXTERNAL;
} }
rec_offs_base(offsets)[1 + i] = offs; rec_offs_base(offsets)[1 + i] = offs;
} while (++i < rec_offs_n_fields(offsets)); } while (++i < rec_offs_n_fields(offsets));
...@@ -459,6 +464,7 @@ rec_get_offsets_reverse( ...@@ -459,6 +464,7 @@ rec_get_offsets_reverse(
ulint n; ulint n;
ulint i; ulint i;
ulint offs; ulint offs;
ulint any_ext;
const byte* nulls; const byte* nulls;
const byte* lens; const byte* lens;
dict_field_t* field; dict_field_t* field;
...@@ -485,6 +491,7 @@ rec_get_offsets_reverse( ...@@ -485,6 +491,7 @@ rec_get_offsets_reverse(
lens = nulls + (index->n_nullable + 7) / 8; lens = nulls + (index->n_nullable + 7) / 8;
i = offs = 0; i = offs = 0;
null_mask = 1; null_mask = 1;
any_ext = 0;
/* read the lengths of fields 0..n */ /* read the lengths of fields 0..n */
do { do {
...@@ -529,6 +536,7 @@ rec_get_offsets_reverse( ...@@ -529,6 +536,7 @@ rec_get_offsets_reverse(
offs += len & 0x3fff; offs += len & 0x3fff;
if (UNIV_UNLIKELY(len & 0x4000)) { if (UNIV_UNLIKELY(len & 0x4000)) {
any_ext = REC_OFFS_EXTERNAL;
len = offs | REC_OFFS_EXTERNAL; len = offs | REC_OFFS_EXTERNAL;
} else { } else {
len = offs; len = offs;
...@@ -548,7 +556,7 @@ rec_get_offsets_reverse( ...@@ -548,7 +556,7 @@ rec_get_offsets_reverse(
ut_ad(lens >= extra); ut_ad(lens >= extra);
*rec_offs_base(offsets) = (lens - extra + REC_N_NEW_EXTRA_BYTES) *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