Commit 66b21ed5 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-30567 rec_get_offsets() is not optimal

rec_init_offsets_comp_ordinary(), rec_init_offsets(),
rec_get_offsets_reverse(), rec_get_nth_field_offs_old():
Simplify some bitwise arithmetics to avoid conditional jumps,
and add branch prediction hints with the assumption that most
variable-length columns are short.

Tested by: Matthias Leich
parent 99ee200b
......@@ -217,14 +217,12 @@ rec_get_n_extern_new(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
if (len & 0x40) {
n_extern++;
}
lens--;
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
if (len & 0x40) {
n_extern++;
}
lens--;
}
}
} while (++i < n);
......@@ -432,24 +430,21 @@ rec_init_offsets_comp_ordinary(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */
if ((len & 0x80) && DATA_BIG_COL(col)) {
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
len <<= 8;
len |= *lens--;
static_assert(STORED_OFFPAGE == 0x4000, "");
static_assert(REC_OFFS_EXTERNAL == 0x4000, "");
const rec_offs ext = len & REC_OFFS_EXTERNAL;
offs += get_value(len);
if (UNIV_UNLIKELY(len & 0x4000)) {
ut_ad(dict_index_is_clust(index));
any |= REC_OFFS_EXTERNAL;
len = combine(offs, STORED_OFFPAGE);
} else {
len = offs;
}
len = offs | ext;
any |= ext;
ut_ad(!ext || index->is_primary());
continue;
}
len = offs += len;
len = offs += static_cast<rec_offs>(len);
} else {
len = offs += field->fixed_len;
}
......@@ -714,23 +709,20 @@ rec_init_offsets(
encoded in two bytes when it is 128 or
more, or when the field is stored
externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
len <<= 8;
len |= *lens--;
/* B-tree node pointers
must not contain externally
stored columns. Thus
the "e" flag must be 0. */
ut_a(!(len & 0x4000));
offs += get_value(len);
len = offs;
goto resolved;
}
if (UNIV_UNLIKELY(len & 0x80)
&& DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
len <<= 8;
len |= *lens--;
/* B-tree node pointers
must not contain externally
stored columns. Thus
the "e" flag must be 0. */
ut_a(!(len & 0x4000));
offs += len & 0x3fff;
len = offs;
goto resolved;
}
len = offs += len;
......@@ -758,26 +750,24 @@ rec_init_offsets(
do {
offs = rec_1_get_field_end_info(rec, i);
if (offs & REC_1BYTE_SQL_NULL_MASK) {
offs &= ~REC_1BYTE_SQL_NULL_MASK;
set_type(offs, SQL_NULL);
offs ^= REC_1BYTE_SQL_NULL_MASK
| SQL_NULL;
}
rec_offs_base(offsets)[1 + i] = offs;
} while (++i < n);
} else {
offs += 2 * static_cast<rec_offs>(n_fields);
offs += static_cast<rec_offs>(2 * n_fields);
any = offs;
/* Determine offsets to fields */
do {
offs = rec_2_get_field_end_info(rec, i);
if (offs & REC_2BYTE_SQL_NULL_MASK) {
offs &= ~REC_2BYTE_SQL_NULL_MASK;
set_type(offs, SQL_NULL);
}
if (offs & REC_2BYTE_EXTERN_MASK) {
offs &= ~REC_2BYTE_EXTERN_MASK;
set_type(offs, STORED_OFFPAGE);
any |= REC_OFFS_EXTERNAL;
}
static_assert(REC_2BYTE_SQL_NULL_MASK
== SQL_NULL, "");
static_assert(REC_2BYTE_EXTERN_MASK
== STORED_OFFPAGE, "");
static_assert(REC_OFFS_EXTERNAL
== STORED_OFFPAGE, "");
any |= (offs & REC_OFFS_EXTERNAL);
rec_offs_base(offsets)[1 + i] = offs;
} while (++i < n);
}
......@@ -1028,23 +1018,18 @@ rec_get_offsets_reverse(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
len <<= 8;
len |= *lens++;
offs += get_value(len);
if (UNIV_UNLIKELY(len & 0x4000)) {
any_ext = REC_OFFS_EXTERNAL;
len = combine(offs,
STORED_OFFPAGE);
} else {
len = offs;
}
goto resolved;
}
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
len &= 0x7f;
len <<= 8;
len |= *lens++;
static_assert(STORED_OFFPAGE == 0x4000, "");
static_assert(REC_OFFS_EXTERNAL == 0x4000, "");
rec_offs ext = len & REC_OFFS_EXTERNAL;
offs += get_value(len);
len = offs | ext;
any_ext |= ext;
goto resolved;
}
len = offs += len;
......@@ -1089,7 +1074,7 @@ rec_get_nth_field_offs_old(
return(os);
}
next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK;
next_os &= ~REC_1BYTE_SQL_NULL_MASK;
} else {
os = rec_2_get_field_start_offs(rec, n);
......@@ -1101,8 +1086,7 @@ rec_get_nth_field_offs_old(
return(os);
}
next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK
| REC_2BYTE_EXTERN_MASK);
next_os &= ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK);
}
*len = next_os - os;
......@@ -1255,7 +1239,8 @@ rec_get_converted_size_comp_prefix_low(
} else if (dfield_is_ext(dfield)) {
ut_ad(DATA_BIG_COL(field->col));
extra_size += 2;
} else if (len < 128 || !DATA_BIG_COL(field->col)) {
} else if (UNIV_LIKELY(len < 128)
|| !DATA_BIG_COL(field->col)) {
extra_size++;
} else {
/* For variable-length columns, we look up the
......@@ -1652,7 +1637,7 @@ rec_convert_dtuple_to_rec_comp(
/* set the null flag if necessary */
if (dfield_is_null(field)) {
*nulls |= null_mask;
*nulls |= static_cast<byte>(null_mask);
null_mask <<= 1;
continue;
}
......@@ -2122,14 +2107,12 @@ rec_copy_prefix_to_buf(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the column is stored externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxx */
len &= 0x3f;
len <<= 8;
len |= *lens--;
UNIV_PREFETCH_R(lens);
}
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxx */
len &= 0x3f;
len <<= 8;
len |= *lens--;
UNIV_PREFETCH_R(lens);
}
prefix_len += len;
}
......
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