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
This commit is contained in:
Marko Mäkelä 2023-03-06 15:32:25 +02:00
parent 99ee200b8b
commit 66b21ed540

View File

@ -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 @@ start:
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(
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 |= *lens--;
len <<= 8; /* B-tree node pointers
len |= *lens--; must not contain externally
stored columns. Thus
/* B-tree node pointers the "e" flag must be 0. */
must not contain externally ut_a(!(len & 0x4000));
stored columns. Thus offs += len & 0x3fff;
the "e" flag must be 0. */ len = offs;
ut_a(!(len & 0x4000)); goto resolved;
offs += get_value(len);
len = offs;
goto resolved;
}
} }
len = offs += len; len = offs += len;
@ -758,26 +750,24 @@ resolved:
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(
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(
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(
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(
} 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 @@ start:
/* 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(
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;
} }