3352 Marko Mäkelä 2011-08-10 [merge]
Merge mysql-5.5 to mysql-trunk.
modified:
storage/innobase/row/row0sel.c
3351 Marc Alff 2011-08-09
Bug#12346211 - PERF IMPACT OF PERFORMANCE-SCHEMA WITH DISABLED INSTRUMENTS/CONSUMERS
Performance improvement #3: Better allocation.
Before this fix, the performance schema allocation algorithm used,
for example when creating a mutex, was:
- compute a random number I between 0 and N
- start to scan for an empty slot at position I modulo N,
I+1 modulo N, I+2 modulo N ...
and this for each competing thread.
When only a few threads are running, and when the slots are mostly empty,
this works well since few collisions happen.
When the number of competing threads augments, and when the slots are mostly
occupied, this code can potentially create a lot of competition between
threads, when doing atomic operations against each slot internal lock.
With this fix, the allocation is changed to:
- keep a static monotonic counter for each buffer, I
- atomically increment I
- look for an empty slot at I modulo N
- repeat if necessary.
Because the monotonic counter is shared between all threads,
competing threads end up actually looking for different slots at I0, I0+1,
I0+2 etc, which prevents competition on each slot internal lock.
Also, because records are allocated in circular fashion, starting to look
for an empty slot after the last slot found increases the probability to
find available slots, and reduces the number of loops during the scan.
While difficult to measure, this fix is expected to improve the scalability
of the performance schema allocation code, which is used for:
- creating a mutex,
- creating a rwlock,
- creating a cond,
- opening a file,
- opening a table
which are all operations that can occur frequently when the server is
running.
modified:
storage/perfschema/pfs_instr.cc
storage/perfschema/pfs_instr_class.cc
storage/perfschema/pfs_setup_actor.cc
storage/perfschema/pfs_setup_object.cc
=== modified file 'storage/innobase/row/row0sel.c'
--- a/storage/innobase/row/row0sel.c revid:marc.alff@strippedph6luqw
+++ b/storage/innobase/row/row0sel.c revid:marko.makela@stripped
@@ -2574,6 +2574,8 @@ row_sel_field_store_in_mysql_format_func
ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len);
+ UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
+ UNIV_MEM_INVALID(dest, templ->mysql_col_len);
switch (templ->type) {
const byte* field_end;
@@ -2612,14 +2614,16 @@ row_sel_field_store_in_mysql_format_func
dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes);
+ /* Copy the actual data. Leave the rest of the
+ buffer uninitialized. */
+ memcpy(dest, data, len);
+ break;
}
/* Copy the actual data */
ut_memcpy(dest, data, len);
- /* Pad with trailing spaces. We pad with spaces also the
- unused end of a >= 5.0.3 true VARCHAR column, just in case
- MySQL expects its contents to be deterministic. */
+ /* Pad with trailing spaces. */
pad = dest + len;
@@ -3227,6 +3231,39 @@ sel_restore_position_for_mysql(
}
/********************************************************************//**
+Copies a cached field for MySQL from the fetch cache. */
+static
+void
+row_sel_copy_cached_field_for_mysql(
+/*================================*/
+ byte* buf, /*!< in/out: row buffer */
+ const byte* cache, /*!< in: cached row */
+ const mysql_row_templ_t*templ) /*!< in: column template */
+{
+ ulint len;
+
+ buf += templ->mysql_col_offset;
+ cache += templ->mysql_col_offset;
+
+ UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
+ && templ->type != DATA_INT) {
+ /* Check for != DATA_INT to make sure we do
+ not treat MySQL ENUM or SET as a true VARCHAR!
+ Find the actual length of the true VARCHAR field. */
+ row_mysql_read_true_varchar(
+ &len, cache, templ->mysql_length_bytes);
+ len += templ->mysql_length_bytes;
+ UNIV_MEM_INVALID(buf, templ->mysql_col_len);
+ } else {
+ len = templ->mysql_col_len;
+ }
+
+ ut_memcpy(buf, cache, len);
+}
+
+/********************************************************************//**
Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE
void
@@ -3238,26 +3275,22 @@ row_sel_dequeue_cached_row_for_mysql(
{
ulint i;
const mysql_row_templ_t*templ;
- byte* cached_rec;
+ const byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
+ UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
+
+ cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
+
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
- cached_rec = prebuilt->fetch_cache[
- prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(cached_rec
- + templ->mysql_col_offset,
- templ->mysql_col_len);
-#endif
- ut_memcpy(buf + templ->mysql_col_offset,
- cached_rec + templ->mysql_col_offset,
- templ->mysql_col_len);
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, templ);
/* Copy NULL bit of the current field from cached_rec
to buf */
if (templ->mysql_null_bit_mask) {
@@ -3267,17 +3300,24 @@ row_sel_dequeue_cached_row_for_mysql(
& (byte)templ->mysql_null_bit_mask;
}
}
+ } else if (prebuilt->mysql_prefix_len > 63) {
+ /* The record is long. Copy it field by field, in case
+ there are some long VARCHAR column of which only a
+ small length is being used. */
+ UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
+
+ /* First copy the NULL bits. */
+ ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
+ /* Then copy the requested fields. */
+
+ for (i = 0; i < prebuilt->n_template; i++) {
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, prebuilt->mysql_template + i);
+ }
+ } else {
+ ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
}
- else {
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
- [prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
-#endif
- ut_memcpy(buf,
- prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
- }
+
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk branch (marko.makela:3351 to 3352) | marko.makela | 10 Aug |