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);
}
}
}
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list