[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