[Mono-dev] patch for String equality/inequality

Atsushi Eno atsushi at ximian.com
Sat Feb 18 03:34:49 EST 2006


Wow, the patch is impressive! Thanks, I support it.

Interestingly it did not result in notable difference in XMLMark.
Having != implementation based on your Equals() implementation
resulted in the best improvement. I think 2% difference in String
inequality is worthy of having different implementation, but just
my 2 cents.

Atsushi Eno

Marek Safar wrote:
> Hello,
>> I noticed that String operator != just reuses == i.e. a != b
>> returns ! (a == b). It could be more effective if operator!=
>> has actual implementation code. Also, string.Equals() currently
>> calls operator!= which performs extraneous null check (maybe
>> static invocation was faster?).
>>
>> As far as I tried with XMLmark, the attached patch certainly
>> improves performance (though not big, about 2%). If it looks
>> good feel free to apply to trunk.
>>   
> I think it is not worthwhile to duplicate all code because of 2 %.
> 
>> I noticed that string op_Equality is slow, about 2x than MS.
>> There might be chances to improve it.
>>   
> I tried to optimize internal method used for Equality and here are
> results of my string.Equal micro benchmark and patch (including both of
> them).
> 
> Micro benchmark results for P-III - 1,13 GHz
> 
> Microsoft runtime v 1.1 - 41,47 sec
> Microsoft runtime v 2.0 - 26,30 sec
> 
> Mono SVN HEAD - 44,00 sec
> Mono SVN HEAD -O=all - 42,09 sec
> 
> Patched Mono SVN HEAD - 26,32 sec
> Patched Mono SVN HEAD -O=all - 25,88 sec
> 
> Patch on Microsoft runtime v 2.0 - 21,65 sec
> 
> The last result I got when I tried to run my new code on Microsoft
> runtime (MS JIT). The result is best of all which basically means that
> we can still improve our JIT compiler ;-)
> 
> 
> For test on Microsoft runtime I used csc with /optimize+ option and mcs
> for Mono tests.
> 
> Any objections to the patch ?
> 
> 
> - Marek
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> Index: C:/CVSROOT/mcs/class/corlib/System/String.cs
> ===================================================================
> --- C:/CVSROOT/mcs/class/corlib/System/String.cs	(revision 57019)
> +++ C:/CVSROOT/mcs/class/corlib/System/String.cs	(working copy)
> @@ -72,28 +72,42 @@
>  			if (len != b.length)
>  				return false;
>  
> -			if (len == 0)
> -				return true;
> +			fixed (char* s1 = &a.start_char, s2 = &b.start_char) {
> +				char* s1_ptr = s1;
> +				char* s2_ptr = s2;
>  
> -			fixed (char * s1 = &a.start_char, s2 = &b.start_char) {
> -				// it must be one char, because 0 len is done above
> -				if (len < 2)
> -					return *s1 == *s2;
> +				while (len >= 8) {
> +					if (((int*)s1_ptr)[0] != ((int*)s2_ptr)[0] ||
> +						((int*)s1_ptr)[1] != ((int*)s2_ptr)[1] ||
> +						((int*)s1_ptr)[2] != ((int*)s2_ptr)[2] ||
> +						((int*)s1_ptr)[3] != ((int*)s2_ptr)[3])
> +						return false;
>  
> -				// check by twos
> -				int * sint1 = (int *) s1, sint2 = (int *) s2;
> -				int n2 = len >> 1;
> -				do {
> -					if (*sint1++ != *sint2++)
> +					s1_ptr += 8;
> +					s2_ptr += 8;
> +					len -= 8;
> +				}
> +
> +				if (len >= 4) {
> +					if (((int*)s1_ptr)[0] != ((int*)s2_ptr)[0] ||
> +						((int*)s1_ptr)[1] != ((int*)s2_ptr)[1])
>  						return false;
> -				} while (--n2 != 0);
>  
> -				// nothing left
> -				if ((len & 1) == 0)
> -					return true;
> +					s1_ptr += 4;
> +					s2_ptr += 4;
> +					len -= 4;
> +				}
>  
> -				// check the last one
> -				return *(char *) sint1 == *(char *) sint2;
> +				if (len > 1) {
> +					if (((int*)s1_ptr)[0] != ((int*)s2_ptr)[0])
> +						return false;
> +
> +					s1_ptr += 2;
> +					s2_ptr += 2;
> +					len -= 2;
> +				}
> +
> +				return len == 0 || *s1_ptr == *s2_ptr;
>  			}
>  		}
>  
> 
> 
> ------------------------------------------------------------------------
> 
> using System;
> 
> namespace ConsoleApplication1 {
> 
> 	class Program {
> 		static void Main(string[] args)
> 		{
> 			string s1 = "original9";
> 			string yes = "original3";
> 			string s2 = "orig945";
> 			string yes2 = "orig943";
> 			string s3 = "original95";
> 			string yes3 = "original96";
> 			string s4 = "original_original_1";
> 			string yes4 = "original_original_0";
> 
> 			const int count = 100000000;
> 
> 			DateTime s = DateTime.Now;
> 			for (int i = 0; i < count; ++i) {
> 				String.Equals(s1, yes);
> 				String.Equals(s3,yes3);
> 				String.Equals(s2,yes2);
> 				String.Equals(s4,yes4);
> 				String.Equals("", "");
> 			}
> 
> 			Console.WriteLine(DateTime.Now - s);
> 		}
> 	}
> }





More information about the Mono-devel-list mailing list