Skip to content

Commit

Permalink
MDEV-30567 rec_get_offsets() is not optimal
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dr-m committed Mar 6, 2023
1 parent 99ee200 commit 66b21ed
Showing 1 changed file with 60 additions and 77 deletions.
137 changes: 60 additions & 77 deletions storage/innobase/rem/rem0rec.cc
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 66b21ed

Please sign in to comment.