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

Reply via email to