diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2023-03-06 15:32:25 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2023-03-06 15:32:25 +0200 |
commit | 66b21ed5403aa4ef18a4c797af353ec3379b152d (patch) | |
tree | 2012ceb451230ffddf56dc4dcb339f045fe45ead | |
parent | 99ee200b8bc8d76469249a828b642f3a1efee2de (diff) | |
download | mariadb-git-66b21ed5403aa4ef18a4c797af353ec3379b152d.tar.gz |
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
-rw-r--r-- | storage/innobase/rem/rem0rec.cc | 137 |
1 files changed, 60 insertions, 77 deletions
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 08682304410..de300bf799a 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -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 @@ start: 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 @@ resolved: 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 @@ start: /* 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; } |