[Mono-devel-list] First CIL Regex performance result

Ben Maurer bmaurer at users.sourceforge.net
Fri Feb 27 15:43:14 EST 2004


Hello,

Are you including compile time? Maybe SRE is slow.

Also, can you try generating a compiled assembly and sending it with a
test case. That would help those of us who dont have the engine set up
get it working.

-- Ben

On Fri, 2004-02-27 at 15:19, Eric Durand Tremblay wrote:
> Hello all,
> 
> We have finished compiling some basic regex with our IL Compilator.  All 
> anchor, character matching, string matching and alternation construct 
> are completed.
> 
> Before we continue our work, I decided to try some benchmark to see if 
> we are in the good way.  The result where disastrous !!!
> 
> For a simple regex like (a|b), our compiled regex is LESS efficient ( 
> take 150% more time ) then interpreted regex.  Note that the algorythms 
> used are exactly the same and that the number of matches is equal in the 
> two approach.
> 
> After taking some time crying, François decided to  try it with the  
> .net runtime.  Results are as expected : OUR compiled regex are MORE 
> efficient ( take 50% less time  then the interpreted ones) when running 
> on the .net runtime.
> 
> So, we taught that maybe, mono dynamic assembly where somehow less 
> efficient than .net ones.  We tryed to bechmark this with absolutely no 
> results.
> 
> You will find a copy of the benchmarks we used attached to this mail.
> 
> Then, if anybody have any idea on the subject, we will be glad to hear it.
> 
> Eric Durand-Tremblay
> TIP-MONO ( a University Laval project)
> Blog : http://aeglos.dyndns.org/tip-mono
> 
> ______________________________________________________________________
> using System;
> using System.Text.RegularExpressions;
> using System.IO;
> 
> namespace RegexBench
> {
> 	class RegexBench
> 	{
> 		private string m_text;
> 		
> 		[STAThread]
> 		static void Main(string[] args)
> 		{
> 			TextReader reader = null;
> 			try
> 			{	
> 				reader = File.OpenText("RegexBench.txt");			
> 				
> 				RegexBench bench = new RegexBench(reader.ReadToEnd());
> 
> 				//***
> 				//To test any regex, just do :
> 				//bench.testRegex("", false);
> 				//with the regex text as first parameter.  To view the results of a regex, use true as second parameter.
> 								
> 				bench.testRegex("a|b", false);
> 				//bench.testRegex("(?<left><(?<inter>[a-zA-Z]+)>)[^<>]*</\\k<inter>>", false); //Balanced html tag (not exactly it)
> 				//bench.testRegex("(\\s[ab]{2,3}\\w+\\s)", false); //Random regex
> 				//bench.testRegex("\\w{3,5}://([\\.]|\\w|\\\\)*", false); //Simple Internet address
> 			       				
> 				//bench.testRegex("[abC-DefgG-Jklm]{5}", false); //Big character class
> 				//bench.testRegex("(\\w|(\\w\\.\\w)|(\\w_\\w)|(\\w\\-\\w))+@(\\w|(\\w\\.\\w)|(\\w_\\w)|(\\w\\-\\w))+\\.\\w{2,4}", false); //E-mail
> 
> 
> 				//Throw exception on mono
> 				//bench.testRegex("(?<left><(?<inter>[a-zA-Z]+)>)[^<>]*(?<right-left></\\k<inter>>)", false);//Balanced html tag (not exactly it)
> 			}
> 			catch(Exception e)
> 			{
> 				Console.WriteLine(e.Message + "\n" +  e.StackTrace);
> 			}
> 			finally
> 			{
> 				try
> 				{
> 					if (reader != null)
> 						reader.Close();
> 				}
> 				catch(Exception){};
> 			}
> 		}
> 
> 		public RegexBench(string text)
> 		{
> 			m_text = text;
> 		}
> 
> 		//Evaluate execution time to find all results of regex "strRegex" in compiled and uncompiled mode.
> 		//To view regex results, put showResult to true;
> 		private void testRegex(string strRegex, bool showResult)
> 		{	
> 			int begin;
> 			int end;
> 			int nbMatch;
> 			double compCompTime;
> 			double compInterTime;
> 			double compTime;
> 			double interTime;
> 			MatchCollection matches;
> 
> 			Console.WriteLine("Testing Regex : {0}", new object[] {strRegex});
> 
> 			//Creation
> 			begin = Environment.TickCount;
> 			Regex regex = new Regex(strRegex);
> 			end = Environment.TickCount;
> 			compInterTime = end - begin;
> 			Console.WriteLine("Creation of interpreted regex : {0}ms", new object[] {compInterTime});
> 			
> 
> 			begin = Environment.TickCount;
> 			Regex regexc = new Regex(strRegex, RegexOptions.Compiled);
> 			end = Environment.TickCount;
> 			compCompTime = end - begin;
> 			Console.WriteLine("Compilation time : {0}ms\n", new object[] {compCompTime});
> 			
> 
> 			//Interpreted Regex
> 			begin = Environment.TickCount;
> 			matches = regex.Matches(m_text);
> 			nbMatch = matches.Count;	//Important, MS do the job here.	
> 			end = Environment.TickCount;
> 			interTime = end - begin;
> 
> 			Console.WriteLine("Elapsed time (Interpreted): {0}ms", new object[]{interTime});
> 			Console.WriteLine("Nb Match : {0}\n", new object[]{nbMatch});
> 
> 
> 			//Compiled Regex
> 			begin = Environment.TickCount;
> 			matches = regexc.Matches(m_text);	
> 			nbMatch = matches.Count;	//Important, MS do the job here.
> 			end = Environment.TickCount;
> 			compTime = end - begin;
> 
> 			Console.WriteLine("Elapsed time (Compiled): {0}ms", new object[]{compTime});
> 			Console.WriteLine("Nb Match : {0}", new object[]{nbMatch});
> 
> 
> 			Console.WriteLine("\nInterpreted compilation ratio : {0}%", (int)(compInterTime / interTime * 100));
> 			Console.WriteLine("Compiled compilation ratio : {0}%", (int)(compCompTime / compTime * 100));
> 			Console.WriteLine("Compiled vs Interpreted (without compile time) : {0}%", (int)(compTime / interTime * 100));
> 			Console.WriteLine("Compiled vs Interpreted (with compile time) : {0}%", (int)((compTime + compCompTime) / (compInterTime + interTime) * 100));
> 			
> 
> 			if( showResult)
> 			{
> 				for(int i=0; i<nbMatch ;i++)
> 				{
> 					Console.WriteLine(matches[i].Captures[0].Value);
> 					Console.WriteLine("---------------------");
> 				}
> 			}
> 
> 			Console.WriteLine("");
> 		}
> 	}
> }
> 
> ______________________________________________________________________
> // created on 2004-02-26 at 09:24
> using System;
> using System.Reflection;
> using System.Reflection.Emit;
> 
> public class MainClass
> {
> 	public static void Main(string[] args)
> 	{
> 		try {
> 			
> 		
> 		int compiledTime = 0;
> 		int dynTime = 0;
> 		int begin;
> 		int end;
> 		long res1 = 0 ;
> 		long res2 = 0;
> 		EmitTestFactory factory = new EmitTestFactory();
> 		
> 		EmitTestBase compiled = factory.getEmitTest(false);
> 		EmitTestBase dynamic = factory.getEmitTest(true);
> 		
> 
> 
> 		
> 		for ( int i = 0; i<=200; i++)
> 		{
> 			begin =  Environment.TickCount;
> 			res1 = compiled.EmitTest();
> 			end = Environment.TickCount;		
> 			compiledTime += end - begin;
> 		}
> 		
> 		compiledTime = compiledTime / 200;
> 		Console.WriteLine("Time for the compiled call {0}ms" , compiledTime);
> 		
> 		for ( int i = 0; i<=200; i++)
> 		{
> 			begin =  Environment.TickCount;
> 			res2 = dynamic.EmitTest();
> 			end = Environment.TickCount;
> 			dynTime += end - begin;
> 		}
> 		
> 
> 		dynTime = dynTime / 200;
> 		
> 		Console.WriteLine("Time for the dynamic call {0}ms ",dynTime);
> 		Console.WriteLine(res1);
> 		Console.WriteLine(res2);
> 		
> 		Console.WriteLine("Compiled vs Dynamic : {0}%", (int)(dynTime /compiledTime* 100));
> 		}
> 		catch (Exception e) 
> 		{
> 			//System.Diagnostics.Debugger.Break();
> 			Console.WriteLine(e.Message + "\n" +  e.StackTrace);
> 		
> 			
> 		
> 		}
> 		
> 		
> 		
> 	}
> 	
> }
> 
> public class EmitTestFactory
> {
> 	public EmitTestBase getEmitTest(bool dynamic)
> 	{
> 		if (dynamic)
> 		{
> 			Type t = this.CreateType();
> 			asmBuilder.Save("Test.dll");
> 			return (EmitTestBase)Activator.CreateInstance(t);
> 			//return new EmitTest1();
> 		}
> 		else
> 		{
> 			return new EmitTest1();
> 		}
> 	}
> 	
> 	private AssemblyBuilder asmBuilder;
> 	private Type CreateType()
> 	{
> 			// Get the current application domain for the current thread.
> 			AppDomain currentDomain = AppDomain.CurrentDomain;
> 		       
> 			AssemblyName asmName = new AssemblyName();
> 			asmName.Name = "Test.dll";
> 
> 
> 			// Define a dynamic assembly in the current application domain.			
> 			asmBuilder = currentDomain.DefineDynamicAssembly (asmName, AssemblyBuilderAccess.RunAndSave);
> 
> 			// Define a dynamic module in this assembly.			
> 			ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("DynModule", asmName.Name);
> 		
> 					// Define a runtime class with specified name and attributes.
> 			TypeBuilder builder = modBuilder.DefineType("EmitTest2" ,
> 							TypeAttributes.Public , 
> 							typeof(EmitTestBase), 
> 							new Type[]{typeof(EmitTestInter)});
> 
> 
> //Define default constructor
> 			ConstructorBuilder ctorBuilder = builder.DefineConstructor(MethodAttributes.Public,
> 										   CallingConventions.Standard,
> 										   new Type[] {});
> 			ILGenerator ctorILGen = ctorBuilder.GetILGenerator();
> 			
> 		
> 
> 			ctorILGen.Emit(OpCodes.Ldarg_0);
> 			ctorILGen.Emit(OpCodes.Call, 
> 				       typeof(EmitTestBase).GetConstructor(BindingFlags.Instance | 
> 									     BindingFlags.NonPublic, 
> 				       null, 
> 				       new Type[]{},
> 				       null));
> 			ctorILGen.Emit(OpCodes.Ret);
> 		
> 
> 
> 			MethodBuilder methodBuilder = builder.DefineMethod("EmitTest", MethodAttributes.Public | MethodAttributes.Virtual ,
> 									       typeof(long), 
> 									       new Type[]{}); 
> 		    
> 			builder.DefineMethodOverride(methodBuilder, typeof(EmitTestInter).GetMethod("EmitTest"));
> 			ILGenerator iLGen = methodBuilder.GetILGenerator();
> 	
> 			Label IL_001c = iLGen.DefineLabel();
> 			Label IL_0010 = iLGen.DefineLabel();
> 			Label IL_000c = iLGen.DefineLabel();
> 			Label IL_0008 = iLGen.DefineLabel();
> 			
> 
> 		
> 		
> //		.method public hidebysig virtual instance void 
> //        EmitTest() cil managed
> //{
> //  // Code size       40 (0x28)
> //  .maxstack  2
> 
> //  .locals init ([0] int32 i,
> //           [1] int64 j)
> 
> 			LocalBuilder i = iLGen.DeclareLocal(typeof(int));
> 			LocalBuilder j = iLGen.DeclareLocal(typeof(int));	
> 			LocalBuilder e = iLGen.DeclareLocal(typeof(long));	
> //  IL_0000:  ldc.i4     0xffff8000
> //  IL_0005:  stloc.0
> 			iLGen.Emit(OpCodes.Ldc_I4, (int)0);
> 			iLGen.Emit(OpCodes.Stloc_0);			
> //  IL_0006:  br.s       IL_001c
> 			iLGen.Emit(OpCodes.Br_S, IL_001c);
> // IL_0008:  ldc.i4.0
> //  IL_0009:  stloc.1
> 			iLGen.MarkLabel(IL_0008);
> 			iLGen.Emit(OpCodes.Ldc_I4, (int)0);
> 			iLGen.Emit(OpCodes.Stloc_1);		
> //  IL_000a:  br.s       IL_0010
> 			iLGen.Emit(OpCodes.Br_S, IL_0010);
> 			
> 
> //  IL_000c:  ldloc.1
> //  IL_000d:  ldc.i4.1
> //  IL_000e:  add
> //  IL_000f:  stloc.1
> 			iLGen.MarkLabel(IL_000c);
> 
> 			iLGen.Emit(OpCodes.Ldloc_2);
> 			iLGen.Emit(OpCodes.Ldc_I4_1);
> 			iLGen.Emit(OpCodes.Conv_U8);
> 
> 			iLGen.Emit(OpCodes.Add);
> 			iLGen.Emit(OpCodes.Stloc_2);
> 
> 			iLGen.Emit(OpCodes.Ldloc_1);
> 			iLGen.Emit(OpCodes.Ldc_I4_1);
> 			iLGen.Emit(OpCodes.Add);
> 			iLGen.Emit(OpCodes.Stloc_1);
> //  IL_0010:  ldloc.1
> //  IL_0011:  ldc.i4     0x7fff
> //  IL_0016:  ble.s      IL_000c
> 			iLGen.MarkLabel(IL_0010);	
> 			iLGen.Emit(OpCodes.Ldloc_1);
> 			iLGen.Emit(OpCodes.Ldc_I4, (int)200);
> 			iLGen.Emit(OpCodes.Ble_S, IL_000c);		
> //  IL_0018:  ldloc.0
> //  IL_0019:  ldc.i4.1
> //  IL_001a:  add
> //  IL_001b:  stloc.0
> 			iLGen.Emit(OpCodes.Ldloc_0);
> 			iLGen.Emit(OpCodes.Ldc_I4_1);
> 			iLGen.Emit(OpCodes.Add);
> 			iLGen.Emit(OpCodes.Stloc_0);
> 			
> //  IL_001c:  ldloc.0
> //  IL_001d:  ldc.i4     0x7fff
> //  IL_0022:  ble.s      IL_0008
> 			iLGen.MarkLabel(IL_001c);	
> 			iLGen.Emit(OpCodes.Ldloc_0);
> 			iLGen.Emit(OpCodes.Ldc_I4, (int)Int16.MaxValue);
> 			iLGen.Emit(OpCodes.Ble_S, IL_0008);
> //	IL_0024:  ret
> 
> //			iLGen.EmitWriteLine(e);
> 			iLGen.Emit(OpCodes.Ldloc_2);
> 			iLGen.Emit(OpCodes.Ret);
> //} // end of method EmitTest1::EmitTest
> 
> 
> 
> 		return builder.CreateType();
> 	}
> }
> 
> 
> interface EmitTestInter
> {
> 	 long EmitTest();
> }
> 
> public abstract class EmitTestBase : EmitTestInter
> {
> 	abstract public long  EmitTest();
> }
> 
> public class EmitTest1 : EmitTestBase
> {
> 	public override long EmitTest()
> 	{
> 		int i;
> 		int j;
> 		long e = 0;
> 		for  (i = 0; i <= Int16.MaxValue; i++)
> 			for ( j = 0; j <= 200; j++)
> 				e++;
> 		//	Console.WriteLine(e);	
> 		return e;
> 	}
> }




More information about the Mono-devel-list mailing list