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