List:Commits« Previous MessageNext Message »
From:marko.makela Date:August 10 2011 10:43am
Subject:bzr push into mysql-trunk branch (marko.makela:3351 to 3352)
View as plain text  
 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.makela10 Aug