List:Internals« Previous MessageNext Message »
From:Marko Mäkelä Date:April 22 2005 2:27pm
Subject:bk commit into 5.0 tree (marko:1.1861)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of marko. When marko does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1861 05/04/22 15:27:11 marko@stripped +3 -0
  InnoDB: Optimize rec_get_offsets(), rec_copy_prefix_to_buf() and
  other rec_ functions based on OProfile measurements on GNU/Linux x86.

  innobase/rem/rem0rec.c
    1.17 05/04/22 15:21:12 marko@stripped +93 -53
    Add UNIV_LIKELY and UNIV_UNLIKELY hints.
    rec_init_offsets(), rec_get_offsets_func(): Optimize for x86.
    rec_set_field_extern_bits(): Move "comp" flag outside the loop.
    rec_copy_prefix_to_buf(): Add UNIV_PREFETCH hints.

  innobase/include/rem0rec.ic
    1.21 05/04/22 15:17:47 marko@stripped +30 -50
    Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
    Remove rec_set_node_ptr_flag().
    Add UNIV_LIKELY and UNIV_UNLIKELY hints.
    Correct a spelling error in comment.
    Simplify rec_get_deleted_flag().

  innobase/include/rem0rec.h
    1.13 05/04/22 15:17:00 marko@stripped +13 -21
    Replace FALSE/TRUE ibool comp with zero/nonzero ulint comp.
    Remove rec_set_node_ptr_flag().

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	marko
# Host:	hundin.mysql.fi
# Root:	/home/marko/mysql-5.0

--- 1.12/innobase/include/rem0rec.h	Thu Mar 10 15:37:37 2005
+++ 1.13/innobase/include/rem0rec.h	Fri Apr 22 15:17:00 2005
@@ -51,7 +51,7 @@
 			/* out: the page offset of the next 
 			chained record */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp);	/* in: TRUE=compact page format */
+	ulint	comp);	/* in: nonzero=compact page format */
 /**********************************************************
 The following function is used to set the next record offset field
 of the record. */
@@ -60,7 +60,7 @@
 rec_set_next_offs(
 /*==============*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	next);	/* in: offset of the next record */
 /**********************************************************
 The following function is used to get the number of fields
@@ -90,7 +90,7 @@
 /*============*/
 			/* out: number of owned records */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp);	/* in: TRUE=compact page format */
+	ulint	comp);	/* in: nonzero=compact page format */
 /**********************************************************
 The following function is used to set the number of owned
 records. */
@@ -99,7 +99,7 @@
 rec_set_n_owned(
 /*============*/
 	rec_t*	rec,		/* in: physical record */
-	ibool	comp,		/* in: TRUE=compact page format */
+	ulint	comp,		/* in: nonzero=compact page format */
 	ulint	n_owned);	/* in: the number of owned */
 /**********************************************************
 The following function is used to retrieve the info bits of
@@ -110,7 +110,7 @@
 /*==============*/
 			/* out: info bits */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp);	/* in: TRUE=compact page format */
+	ulint	comp);	/* in: nonzero=compact page format */
 /**********************************************************
 The following function is used to set the info bits of a record. */
 UNIV_INLINE
@@ -118,7 +118,7 @@
 rec_set_info_bits(
 /*==============*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	bits);	/* in: info bits */
 /**********************************************************
 The following function retrieves the status bits of a new-style record. */
@@ -147,7 +147,7 @@
 /*=========================*/
 			/* out: info bits */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp);	/* in: TRUE=compact page format */
+	ulint	comp);	/* in: nonzero=compact page format */
 /**********************************************************
 The following function is used to set the info and status
 bits of a record.  (Only compact records have status bits.) */
@@ -156,7 +156,7 @@
 rec_set_info_and_status_bits(
 /*=========================*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	bits);	/* in: info bits */
 
 /**********************************************************
@@ -167,7 +167,7 @@
 /*=================*/
 			/* out: TRUE if delete marked */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp);	/* in: TRUE=compact page format */
+	ulint	comp);	/* in: nonzero=compact page format */
 /**********************************************************
 The following function is used to set the deleted bit. */
 UNIV_INLINE
@@ -175,7 +175,7 @@
 rec_set_deleted_flag(
 /*=================*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ibool	flag);	/* in: TRUE if delete marked */
 /**********************************************************
 The following function tells if a new-style record is a node pointer. */
@@ -186,14 +186,6 @@
 			/* out: TRUE if node pointer */
 	rec_t*	rec);	/* in: physical record */
 /**********************************************************
-The following function is used to flag a record as a node pointer. */
-UNIV_INLINE
-void
-rec_set_node_ptr_flag(
-/*=================*/
-	rec_t*	rec,	/* in: physical record */
-	ibool	flag);	/* in: TRUE if the record is a node pointer */
-/**********************************************************
 The following function is used to get the order number
 of the record in the heap of the index page. */
 UNIV_INLINE
@@ -202,7 +194,7 @@
 /*=============*/
 			/* out: heap order number */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp);	/* in: TRUE=compact page format */
+	ulint	comp);	/* in: nonzero=compact page format */
 /**********************************************************
 The following function is used to set the heap number
 field in the record. */
@@ -211,7 +203,7 @@
 rec_set_heap_no(
 /*=============*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	heap_no);/* in: the heap number */
 /**********************************************************
 The following function is used to test whether the data offsets
@@ -305,7 +297,7 @@
 Determine if the offsets are for a record in the new
 compact format. */
 UNIV_INLINE
-ibool
+ulint
 rec_offs_comp(
 /*==========*/
 				/* out: TRUE if compact format */

--- 1.20/innobase/include/rem0rec.ic	Wed Feb  2 22:50:28 2005
+++ 1.21/innobase/include/rem0rec.ic	Fri Apr 22 15:17:47 2005
@@ -265,7 +265,7 @@
 			/* out: the page offset of the next chained record, or
 			0 if none */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp)	/* in: TRUE=compact page format */
+	ulint	comp)	/* in: nonzero=compact page format */
 {	
 	ulint	field_value;
 		
@@ -312,7 +312,7 @@
 rec_set_next_offs(
 /*==============*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	next)	/* in: offset of the next record, or 0 if none */
 {
 	ut_ad(rec);
@@ -414,7 +414,7 @@
 {
 	ut_ad(rec);
 	ut_ad(index);
-	if (!index->table->comp) {
+	if (UNIV_UNLIKELY(!index->table->comp)) {
 		return(rec_get_n_fields_old(rec));
 	}
 	switch (rec_get_status(rec)) {
@@ -440,7 +440,7 @@
 /*============*/
 			/* out: number of owned records */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp)	/* in: TRUE=compact page format */
+	ulint	comp)	/* in: nonzero=compact page format */
 {
 	ulint	ret;
 
@@ -461,7 +461,7 @@
 rec_set_n_owned(
 /*============*/
 	rec_t*	rec,		/* in: physical record */
-	ibool	comp,		/* in: TRUE=compact page format */
+	ulint	comp,		/* in: nonzero=compact page format */
 	ulint	n_owned)	/* in: the number of owned */
 {
 	ut_ad(rec);
@@ -480,7 +480,7 @@
 /*==============*/
 			/* out: info bits */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp)	/* in: TRUE=compact page format */
+	ulint	comp)	/* in: nonzero=compact page format */
 {
 	ulint	ret;
 
@@ -501,7 +501,7 @@
 rec_set_info_bits(
 /*==============*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	bits)	/* in: info bits */
 {
 	ut_ad(rec);
@@ -537,14 +537,14 @@
 /*=========================*/
 			/* out: info bits */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp)	/* in: TRUE=compact page format */
+	ulint	comp)	/* in: nonzero=compact page format */
 {
 	ulint	bits;
 #if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
 & (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
 # error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
 #endif
-	if (comp) {
+	if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
 		bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec);
 	} else {
 		bits = rec_get_info_bits(rec, FALSE);
@@ -560,7 +560,7 @@
 rec_set_info_and_status_bits(
 /*=========================*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	bits)	/* in: info bits */
 {
 #if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
@@ -583,14 +583,15 @@
 /*=================*/
 			/* out: TRUE if delete marked */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp)	/* in: TRUE=compact page format */
+	ulint	comp)	/* in: nonzero=compact page format */
 {
-	if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) {
-
-		return(TRUE);
+	if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
+		return(0 != rec_get_bit_field_1(rec, REC_NEW_INFO_BITS,
+				REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT));
+	} else {
+		return(0 != rec_get_bit_field_1(rec, REC_OLD_INFO_BITS,
+				REC_INFO_DELETED_FLAG, REC_INFO_BITS_SHIFT));
 	}
-
-	return(FALSE);
 }
 
 /**********************************************************
@@ -600,24 +601,23 @@
 rec_set_deleted_flag(
 /*=================*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ibool	flag)	/* in: TRUE if delete marked */
 {
-	ulint	old_val;
-	ulint	new_val;
+	ulint	val;
 
 	ut_ad(TRUE == 1);
 	ut_ad(flag <= TRUE);
 
-	old_val = rec_get_info_bits(rec, comp);
+	val = rec_get_info_bits(rec, comp);
 	
 	if (flag) {
-		new_val = REC_INFO_DELETED_FLAG | old_val;
+		val |= REC_INFO_DELETED_FLAG;
 	} else {
-		new_val = ~REC_INFO_DELETED_FLAG & old_val;
+		val &= ~REC_INFO_DELETED_FLAG;
 	}
 
-	rec_set_info_bits(rec, comp, new_val);
+	rec_set_info_bits(rec, comp, val);
 }
 
 /**********************************************************
@@ -633,26 +633,6 @@
 }
 
 /**********************************************************
-The following function is used to flag a record as a node pointer. */
-UNIV_INLINE
-void
-rec_set_node_ptr_flag(
-/*=================*/
-	rec_t*	rec,	/* in: physical record */
-	ibool	flag)	/* in: TRUE if the record is a node pointer */
-{
-	ulint	status;
-	ut_ad(flag <= TRUE);
-	ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec));
-	if (flag) {
-		status = REC_STATUS_NODE_PTR;
-	} else {
-		status = REC_STATUS_ORDINARY;
-	}
-	rec_set_status(rec, status);
-}
-
-/**********************************************************
 The following function is used to get the order number of the record in the
 heap of the index page. */
 UNIV_INLINE
@@ -661,7 +641,7 @@
 /*=============*/
 			/* out: heap order number */
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp)	/* in: TRUE=compact page format */
+	ulint	comp)	/* in: nonzero=compact page format */
 {
 	ulint	ret;
 
@@ -682,7 +662,7 @@
 rec_set_heap_no(
 /*=============*/
 	rec_t*	rec,	/* in: physical record */
-	ibool	comp,	/* in: TRUE=compact page format */
+	ulint	comp,	/* in: nonzero=compact page format */
 	ulint	heap_no)/* in: the heap number */
 {
 	ut_ad(heap_no <= REC_MAX_HEAP_NO);
@@ -843,7 +823,7 @@
 {
 	ulint	i	= rec_offs_n_fields(offsets);
 	ulint	last	= ULINT_MAX;
-	ibool	comp	= (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0;
+	ulint	comp	= *rec_offs_base(offsets) & REC_OFFS_COMPACT;
 
 	if (rec) {
 		ut_ad((ulint) rec == offsets[2]);
@@ -926,7 +906,7 @@
 	ut_ad(n < rec_offs_n_fields(offsets));
 	ut_ad(len);
 
-	if (n == 0) {
+	if (UNIV_UNLIKELY(n == 0)) {
 		field = rec;
 	} else {
 		field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK);
@@ -1037,7 +1017,7 @@
 				where rec is, or NULL; in the NULL case
 				we do not write to log about the change */
 {
-	if (index->table->comp) {
+	if (UNIV_LIKELY(index->table->comp)) {
 		rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr);
 	} else {
 		rec_set_nth_field_extern_bit_old(rec, i, val, mtr);
@@ -1048,7 +1028,7 @@
 Returns the offset of n - 1th field end if the record is stored in the 1-byte
 offsets form. If the field is SQL null, the flag is ORed in the returned
 value. This function and the 2-byte counterpart are defined here because the
-C-compilerwas not able to sum negative and positive constant offsets, and
+C-compiler was not able to sum negative and positive constant offsets, and
 warned of constant arithmetic overflow within the compiler. */
 UNIV_INLINE
 ulint
@@ -1452,7 +1432,7 @@
 				? dict_index_get_n_unique_in_tree(index) + 1
 				: dict_index_get_n_fields(index)));
 
-	if (index->table->comp) {
+	if (UNIV_LIKELY(index->table->comp)) {
 		return(rec_get_converted_size_new(index, dtuple));
 	}
 

--- 1.16/innobase/rem/rem0rec.c	Thu Apr 21 14:23:17 2005
+++ 1.17/innobase/rem/rem0rec.c	Fri Apr 22 15:21:12 2005
@@ -159,22 +159,20 @@
 	ulint*		offsets)/* in/out: array of offsets;
 				in: n=rec_offs_n_fields(offsets) */
 {
-	ulint	n_fields = rec_offs_n_fields(offsets);
 	ulint	i	= 0;
 	ulint	offs;
 
 	rec_offs_make_valid(rec, index, offsets);
 
-	if (index->table->comp) {
+	if (UNIV_LIKELY(index->table->comp)) {
 		const byte*	nulls;
 		const byte*	lens;
 		dict_field_t*	field;
-		dtype_t*	type;
 		ulint		null_mask;
 		ulint		status = rec_get_status(rec);
 		ulint		n_node_ptr_field = ULINT_UNDEFINED;
 
-		switch (status) {
+		switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
 		case REC_STATUS_INFIMUM:
 		case REC_STATUS_SUPREMUM:
 			/* the field is 8 bytes long */
@@ -196,56 +194,74 @@
 		null_mask = 1;
 
 		/* read the lengths of fields 0..n */
-		for (; i < n_fields; i++) {
-			ibool	is_null = FALSE, is_external = FALSE;
+		do {
 			ulint	len;
-			if (i == n_node_ptr_field) {
-				len = 4;
+			if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
+				len = offs += 4;
 				goto resolved;
 			}
 
 			field = dict_index_get_nth_field(index, i);
-			type = dict_col_get_type(dict_field_get_col(field));
-			if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+			if (!(dtype_get_prtype(dict_col_get_type(
+						dict_field_get_col(field)))
+						& DATA_NOT_NULL)) {
 				/* nullable field => read the null flag */
-				is_null = (*nulls & null_mask) != 0;
-				null_mask <<= 1;
-				if (null_mask == 0x100) {
+
+				if (UNIV_UNLIKELY(!(byte) null_mask)) {
 					nulls--;
 					null_mask = 1;
 				}
+
+				if (*nulls & null_mask) {
+					null_mask <<= 1;
+					/* No length is stored for NULL fields.
+					We do not advance offs, and we set
+					the length to zero and enable the
+					SQL NULL flag in offsets[]. */
+					len = REC_OFFS_SQL_NULL;
+					goto resolved;
+				}
+				null_mask <<= 1;
+
+				ut_ad(!field->fixed_len);
+				goto variable_length;
 			}
 
-			if (is_null) {
-				/* No length is stored for NULL fields. */
-				len = 0;
-			} else if (!field->fixed_len) {
+			if (UNIV_UNLIKELY(!field->fixed_len)) {
+				dtype_t*	type;
+			variable_length:
 				/* Variable-length field: read the length */
+				type = dict_col_get_type(
+						dict_field_get_col(field));
 				len = *lens--;
-				if (dtype_get_len(type) > 255
-				    || dtype_get_mtype(type) == DATA_BLOB) {
+				if (UNIV_UNLIKELY(dtype_get_len(type) > 255)
+				    || UNIV_UNLIKELY(dtype_get_mtype(type)
+							== DATA_BLOB)) {
 					if (len & 0x80) {
 						/* 1exxxxxxx xxxxxxxx */
-						is_external = !!(len & 0x40);
-						len &= 0x3f;
 						len <<= 8;
 						len |= *lens--;
+
+						offs += len & 0x3fff;
+						if (UNIV_UNLIKELY(len
+								& 0x4000)) {
+							len = offs
+							| REC_OFFS_EXTERNAL;
+						} else {
+							len = offs;
+						}
+
+						goto resolved;
 					}
 				}
+
+				len = offs += len;
 			} else {
-				len = field->fixed_len;
+				len = offs += field->fixed_len;
 			}
 		resolved:
-			offs += len;
-			len = offs;
-			if (is_external) {
-				len |= REC_OFFS_EXTERNAL;
-			}
-			if (is_null) {
-				len |= REC_OFFS_SQL_NULL;
-			}
 			rec_offs_base(offsets)[i + 1] = len;
-		}
+		} while (++i < rec_offs_n_fields(offsets));
 
 		*rec_offs_base(offsets) =
 			(rec - (lens + 1)) | REC_OFFS_COMPACT;
@@ -253,22 +269,22 @@
 		/* Old-style record: determine extra size and end offsets */
 		offs = REC_N_OLD_EXTRA_BYTES;
 		if (rec_get_1byte_offs_flag(rec)) {
-			offs += n_fields;
+			offs += rec_offs_n_fields(offsets);
 			*rec_offs_base(offsets) = offs;
 			/* Determine offsets to fields */
-			for (; i < n_fields; i++) {
+			do {
 				offs = rec_1_get_field_end_info(rec, i);
 				if (offs & REC_1BYTE_SQL_NULL_MASK) {
 					offs &= ~REC_1BYTE_SQL_NULL_MASK;
 					offs |= REC_OFFS_SQL_NULL;
 				}
 				rec_offs_base(offsets)[1 + i] = offs;
-			}
+			} while (++i < rec_offs_n_fields(offsets));
 		} else {
-			offs += 2 * n_fields;
+			offs += 2 * rec_offs_n_fields(offsets);
 			*rec_offs_base(offsets) = offs;
 			/* Determine offsets to fields */
-			for (; i < n_fields; i++) {
+			do {
 				offs = rec_2_get_field_end_info(rec, i);
 				if (offs & REC_2BYTE_SQL_NULL_MASK) {
 					offs &= ~REC_2BYTE_SQL_NULL_MASK;
@@ -279,7 +295,7 @@
 					offs |= REC_OFFS_EXTERNAL;
 				}
 				rec_offs_base(offsets)[1 + i] = offs;
-			}
+			} while (++i < rec_offs_n_fields(offsets));
 		}
 	}
 }
@@ -310,8 +326,9 @@
 	ut_ad(index);
 	ut_ad(heap);
 
-	if (index->table->comp) {
-		switch (rec_get_status(rec)) {
+	if (UNIV_LIKELY(index->table->comp)) {
+		switch (UNIV_EXPECT(rec_get_status(rec),
+				REC_STATUS_ORDINARY)) {
 		case REC_STATUS_ORDINARY:
 			n = dict_index_get_n_fields(index);
 			break;
@@ -331,13 +348,14 @@
 		n = rec_get_n_fields_old(rec);
 	}
 
-	if (n_fields < n) {
+	if (UNIV_UNLIKELY(n_fields < n)) {
 		n = n_fields;
 	}
 
 	size = n + (1 + REC_OFFS_HEADER_SIZE);
 
-	if (!offsets || rec_offs_get_n_alloc(offsets) < size) {
+	if (UNIV_UNLIKELY(!offsets) ||
+			UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) {
 		if (!*heap) {
 			*heap = mem_heap_create_func(size * sizeof(ulint),
 				NULL, MEM_HEAP_DYNAMIC, file, line);
@@ -652,9 +670,17 @@
 				to log about the change */
 {
 	ulint	i;
-	
-	for (i = 0; i < n_fields; i++) {
-		rec_set_nth_field_extern_bit(rec, index, vec[i], TRUE, mtr);
+
+	if (UNIV_LIKELY(index->table->comp)) {
+		for (i = 0; i < n_fields; i++) {
+			rec_set_nth_field_extern_bit_new(rec, index, vec[i],
+								TRUE, mtr);
+		}
+	} else {
+		for (i = 0; i < n_fields; i++) {
+			rec_set_nth_field_extern_bit_old(rec, vec[i],
+								TRUE, mtr);
+		}
 	}
 }
 
@@ -949,7 +975,7 @@
 	ut_ad(dtuple_validate(dtuple));
 	ut_ad(dtuple_check_typed(dtuple));
 
-	if (index->table->comp) {
+	if (UNIV_LIKELY(index->table->comp)) {
 		rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
 	} else {
 		rec = rec_convert_dtuple_to_rec_old(buf, dtuple);
@@ -1078,17 +1104,19 @@
 					for the copied prefix, or NULL */
 	ulint*		buf_size)	/* in/out: buffer size */
 {
-	byte*		nulls	= rec - (REC_N_NEW_EXTRA_BYTES + 1);
-	byte*		lens	= nulls - (index->n_nullable + 7) / 8;
+	byte*		nulls;
+	byte*		lens;
 	dict_field_t*	field;
 	dtype_t*	type;
 	ulint		i;
-	ulint		prefix_len	= 0;
+	ulint		prefix_len;
 	ibool		is_null;
-	ulint		null_mask	= 1;
+	ulint		null_mask;
 	ulint		status;
 
-	if (!index->table->comp) {
+	UNIV_PREFETCH_RW(*buf);
+
+	if (UNIV_UNLIKELY(!index->table->comp)) {
 		ut_ad(rec_validate_old(rec));
 		return(rec_copy_prefix_to_buf_old(rec, n_fields,
 			rec_get_field_start_offs(rec, n_fields),
@@ -1109,10 +1137,16 @@
 	case REC_STATUS_SUPREMUM:
 		/* infimum or supremum record: no sense to copy anything */
 	default:
-		ut_a(0);
+		ut_error;
 		return(NULL);
 	}
 
+	nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+	lens = nulls - (index->n_nullable + 7) / 8;
+	UNIV_PREFETCH_R(lens);
+	prefix_len = 0;
+	null_mask = 1;
+
 	/* read the lengths of fields 0..n */
 	for (i = 0; i < n_fields; i++) {
 		field = dict_index_get_nth_field(index, i);
@@ -1122,8 +1156,11 @@
 			/* nullable field => read the null flag */
 			is_null = !!(*nulls & null_mask);
 			null_mask <<= 1;
-			if (null_mask == 0x100)
-				nulls--, null_mask = 1;
+			if (null_mask == 0x100) {
+				--nulls;
+				UNIV_PREFETCH_R(nulls);
+				null_mask = 1;
+			}
 		}
 
 		if (is_null) {
@@ -1138,11 +1175,14 @@
 					len &= 0x3f;
 					len <<= 8;
 					len |= *lens--;
+					UNIV_PREFETCH_R(lens);
 				}
 			}
 			prefix_len += len;
 		}
 	}
+
+	UNIV_PREFETCH_R(rec + prefix_len);
 
 	prefix_len += rec - (lens + 1);
 
Thread
bk commit into 5.0 tree (marko:1.1861)Marko Mäkelä22 Apr