using System.Threading.Tasks; namespace TestPooling { using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using DirtyList; using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration; using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool; using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions; using HeuristicLab.Problems.ProgramSynthesis.Push.Extensions; using HeuristicLab.Problems.ProgramSynthesis.Push.Generators.CodeGenerator; using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter; using HeuristicLab.Problems.ProgramSynthesis.Push.Parser; using HeuristicLab.Problems.ProgramSynthesis.Push.Simplifier; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; using HeuristicLab.Random; class Program { private const int PartitionSize = 512; private const int ExampleCount = 200; private const int InstanceCount = 1024; private const int PopulationCount = 1000; private static int TotalInstanceCount => PopulationCount * InstanceCount * ExampleCount; static void Main(string[] args) { // object pooling //Test1(); //Test1_2(); //Test3(); //TestCollectionPooling(); //DirtyListTest(); //TestAddRangeNConcat(); //TestStacks(); //SimpleTest(); //Stepwise().Wait(); //PerformanceTestInterpreter(); //PerformanceParallelTestInterpreter(); //PerformanceTestLinearCodeGenerator(); //TestRobustness(); //TestPool(); //TestPoolPerformance(); //TestSimplifier(); //FlagsTest(); //TestExpressionDependencies(); //TestSplitLogic(); //TestStringBuilder(); //TestRandomReset(); //TestRandomBiased(0, 4, 0.01); //TestRandomBiased(0, 4, 0.25); //TestRandomBiased(0, 4, 0.5); //TestRandomBiased(0, 4, 1); //TestRandomBiased(0, 4, 2); //TestRandomBiased(0, 4, 3); //TestRandomBiased(0, 4, 4); TestOverflowException(); Console.WriteLine("\nPress any key to continue..."); Console.ReadKey(false); } private static void TestOverflowException() { // overflow //var x = long.MinValue / -1; var y = unchecked(long.MaxValue + long.MaxValue); var z = unchecked((long)double.MaxValue); var a = double.MaxValue + (double.MaxValue - 1); } private static void TestRandomBiased(int min, int max, double bias) { var random = new MersenneTwister(); var total = 100000; var distribution = Enumerable .Range(0, total) .Select(_ => random.NextBiased(min, max, bias)) .GroupBy(x => x) .OrderBy(g => g.Key) .ToDictionary(g => g.Key, g => g.Count() / (double)total * 100); Console.WriteLine($@"{min}|{max}|{bias}"); foreach (var entry in distribution) { Console.WriteLine($@"{entry.Key}: {entry.Value}"); } Console.WriteLine(); } private static void TestStringBuilder() { var sb = new StringBuilder(); sb.Append("test"); var s1 = sb.ToString(); var s2 = sb.ToString(); // false var equal = ReferenceEquals(s1, s2); } private static void TestRandomReset() { var random = new MersenneTwister(1000); var x = random.Next(); random.Reset(); var y = random.Next(); if (x != y) { throw new InvalidOperationException(); } } private static void TestSplitLogic() { var sw = new Stopwatch(); var iMax = 100000000u; var repeats = 10; var or = new BooleanOrExpression(); var and = new BooleanAndExpression(); var ors = new Expression[iMax]; var ands = new Expression[iMax]; var booleans = new bool[iMax]; for (var i = 0u; i < iMax; i++) { ors[i] = or; ands[i] = and; booleans[i] = i % 2 == 0; } var orsProgram = new PushProgram(ors); var andsProgram = new PushProgram(ands); using (var interpreter = new PushInterpreter()) { for (var i = 0u; i < repeats; i++) { interpreter.BooleanStack.Push(booleans); sw.Start(); interpreter.Run(orsProgram); sw.Stop(); interpreter.Reset(); } Console.WriteLine("ors:\t" + sw.ElapsedTicks / repeats + " - " + sw.ElapsedMilliseconds); sw.Reset(); interpreter.Reset(); for (var i = 0u; i < repeats; i++) { interpreter.BooleanStack.Push(booleans); sw.Start(); interpreter.Run(andsProgram); sw.Stop(); interpreter.Reset(); } Console.WriteLine("ands:\t" + sw.ElapsedTicks / repeats + " - " + sw.ElapsedMilliseconds); sw.Reset(); interpreter.Reset(); for (var i = 0u; i < repeats; i++) { interpreter.BooleanStack.Push(booleans); sw.Start(); interpreter.Run(orsProgram); sw.Stop(); interpreter.Reset(); } Console.WriteLine("ors:\t" + sw.ElapsedTicks / repeats + " - " + sw.ElapsedMilliseconds); sw.Reset(); interpreter.Reset(); for (var i = 0u; i < repeats; i++) { interpreter.BooleanStack.Push(booleans); sw.Start(); interpreter.Run(andsProgram); sw.Stop(); interpreter.Reset(); } Console.WriteLine("ands:\t" + sw.ElapsedTicks / repeats + " - " + sw.ElapsedMilliseconds); } } private static void TestExpressionDependencies() { var enabledExpressions = ExpressionTable.GetExpressionsByStackTypes(StackTypes.Boolean | StackTypes.Integer); } private static void FlagsTest() { var types = StackTypes.Boolean | StackTypes.Char | StackTypes.Integer; StackTypes test1 = (StackTypes)(StackTypes.Boolean - types); StackTypes test2 = (StackTypes)((StackTypes.Boolean | StackTypes.Float) - types); StackTypes test3 = ((StackTypes.Boolean | StackTypes.Float) & types); StackTypes test4 = ((StackTypes.Boolean | StackTypes.Float) ^ types); StackTypes test5 = ((StackTypes.Boolean | StackTypes.Float) | types); StackTypes test6 = (StackTypes.Boolean | StackTypes.Float) & ~types; StackTypes test7 = StackTypes.Boolean & ~types; } private static void TestStacks() { var sw = new Stopwatch(); var stack = new DirtyList.PushStack(); var stack2 = new PushStack2(); var stack3 = new PushStack3(); var listC = new List(1000); var count = 200000; var repeats = 10; for (var i = 0; i < 100; i++) { listC.Add(i); } sw.Start(); for (var j = 0; j < repeats; j++) { stack.Clear(); for (int i = 0; i < count; i++) { stack.Push(listC); } } sw.Stop(); Console.WriteLine("{0}", sw.ElapsedMilliseconds / repeats); sw.Restart(); for (var j = 0; j < repeats; j++) { stack2.Clear(); for (int i = 0; i < count; i++) { stack2.PushRange(listC); } } sw.Stop(); Console.WriteLine("{0}", sw.ElapsedMilliseconds / repeats); sw.Restart(); for (var j = 0; j < repeats; j++) { stack3.Clear(); for (int i = 0; i < count; i++) { stack3.PushRange(listC); } } sw.Stop(); Console.WriteLine("{0}", sw.ElapsedMilliseconds / repeats); sw.Restart(); for (int i = 0; i < count * listC.Count; i++) { stack.Pop(); } Console.WriteLine("{0}", sw.ElapsedMilliseconds); sw.Restart(); for (int i = 0; i < count * listC.Count; i++) { stack2.Pop(); } Console.WriteLine("{0}", sw.ElapsedMilliseconds); } private static void TestAddRangeNConcat() { var sw = new Stopwatch(); var count = 10000; var listA = new List(); var listB = new List(); var listC = new List(1000); for (var i = 0; i < 1000; i++) { listC.Add(i); } sw.Start(); for (int i = 0; i < count; i++) { listA.AddRange(listC); } sw.Stop(); Console.WriteLine("{0}", sw.ElapsedMilliseconds); sw.Restart(); for (int i = 0; i < count; i++) { listB = listB.Concat(listC).ToList(); } sw.Stop(); Console.WriteLine("{0}", sw.ElapsedMilliseconds); } private static void DirtyListTest() { var sw = new Stopwatch(); var provider = new ManagedPoolProvider(100, () => new Person()); var provider2 = new ManagedPoolProvider(100, () => new Person()); var dl = new DirtyList(); var l = new List(); sw.Start(); for (var i = 0; i < 30000000; i++) { using (var pool = provider.CreatePool()) { for (var j = 0; j < 2; j++) { var person = pool.Get(); person.Age = i + j; person.Name = (i + j).ToString(); dl.Add(person); } } dl.Clear(); } sw.Stop(); Console.WriteLine("DirtyList: {0}", sw.Elapsed.TotalSeconds); sw.Restart(); for (var i = 0; i < 30000000; i++) { using (var pool = provider2.CreatePool()) { for (var j = 0; j < 2; j++) { var person = pool.Get(); person.Age = i + j; person.Name = (i + j).ToString(); l.Add(person); } } l.Clear(); } sw.Stop(); Console.WriteLine("List: {0}", sw.Elapsed.TotalSeconds); } private static void TestCollectionPooling() { var sw = new Stopwatch(); sw.Start(); var provider = new ManagedPoolProvider>(PartitionSize, () => new PooledList()); Parallel.For(0, PopulationCount, pc => { for (var e = 0; e < ExampleCount; e++) { using (var pool = provider.CreatePool()) { var list = pool.Get(); for (var i = 0; i < InstanceCount; i++) list.Add(new Person { Age = pc + e + i, Name = string.Format("{0} - {1} - {2}", pc, e, i) }); } } }); sw.Stop(); Console.WriteLine("Collection Pooling - Duration: {0} - {1} for {2}/{3} instances", sw.ElapsedTicks, sw.Elapsed.TotalSeconds, provider.InstanceCount, TotalInstanceCount); } private static void Test1_2() { var sw = new Stopwatch(); sw.Start(); var provider = new ManagedPoolProvider(PartitionSize, () => new Person()); Parallel.For(0, PopulationCount, pc => { for (var e = 0; e < ExampleCount; e++) { using (var pool = provider.CreatePool()) { for (var i = 0; i < InstanceCount; i++) { var person = pool.Get(); person.Age = pc + e + i; person.Name = string.Format("{0} - {1} - {2}", pc, e, i); } } } }); sw.Stop(); Console.WriteLine("1_2 - Duration: {0} - {1} for {2}/{3} instances", sw.ElapsedTicks, sw.Elapsed.TotalSeconds, provider.InstanceCount, TotalInstanceCount); } private static void Test3() { var count = 0; var sw = new Stopwatch(); sw.Start(); Parallel.For(0, PopulationCount, pc => { for (var e = 0; e < ExampleCount; e++) { var list = new Person[InstanceCount]; for (var i = 0; i < InstanceCount; i++) { list[i] = new Person { Age = pc + e + i, Name = string.Format("{0} - {1} - {2}", pc, e, i) }; } Interlocked.Add(ref count, list.Length); } }); sw.Stop(); Console.WriteLine("3 - Duration: {0} - {1}", sw.ElapsedTicks, sw.Elapsed.TotalSeconds); Console.WriteLine("PartitionSize: {0}", count); } private static void Test2() { var pool = new ObjectPool(() => new Person(), 2048); Parallel.For(0, 10000, i => { for (var j = 0; j < 3000; j++) { var person = pool.Allocate(); person.Age = i + j; person.Name = string.Format("{0} - {1}", i, j); } //pool.Free() }); } static void SimpleTest() { var interpreter = new PushInterpreter(); interpreter.Run("5 INTEGER.DUP INTEGER.+"); interpreter.PrintStacks(); } static async Task Stepwise() { var interpreter = new PushInterpreter(); interpreter.Run("( 0 2 CODE.QUOTE ( 1 INTEGER.+ 0 3 CODE.QUOTE ( 1 INTEGER.+ INTEGER.* ) CODE.DO*RANGE INTEGER.+ ) CODE.DO*RANGE )"); while (!interpreter.IsCompleted) { Console.Clear(); interpreter.PrintStacks(); interpreter.Step(); var input = Console.ReadKey(); if (input.Key == ConsoleKey.Escape) { break; } else if (input.Key == ConsoleKey.Spacebar) { await interpreter.ResumeAsync(); } } Console.Clear(); interpreter.PrintStacks(); } static void PerformanceTestInterpreter() { var program = PushParser.Parse("( 5 INTEGER.DUP INTEGER.+ )"); var interpreter = new PushInterpreter(); var sw = new Stopwatch(); sw.Start(); for (var i = 0; i < 60000000; i++) { interpreter.Run(program); interpreter.ClearStacks(); } sw.Stop(); Console.WriteLine(sw.Elapsed); } static void PerformanceParallelTestInterpreter() { var program = PushParser.Parse("( 5 INTEGER.DUP INTEGER.+ )"); var sw = new Stopwatch(); var iterations = 100; var amount = 600000; var pool = new PushInterpreterPool(iterations, 1024); sw.Start(); Parallel.For(0, iterations, i => { using (var interpreter = pool.Create()) { for (var j = 0; j < amount; j++) { interpreter.Run(program); interpreter.ClearStacks(); } } }); sw.Stop(); Console.WriteLine(sw.Elapsed); } static void PerformanceTestRecursiveCodeGenerator() { var sw = new Stopwatch(); var random = new FastRandom(1337); sw.Start(); var expressions = RecursiveCodeGenerator.RandomCode(60000000, random).ToList(); sw.Stop(); Console.WriteLine("Generated {0} in {1}", expressions.Count, sw.Elapsed); } static void PerformanceTestLinearCodeGenerator() { var sw = new Stopwatch(); var random = new FastRandom(1337); var config = new PushConfiguration(); sw.Start(); var expressions = LinearCodeGenerator.RandomCode(60000000, null, random, config).ToList(); sw.Stop(); Console.WriteLine("Generated {0} in {1}", expressions.Count, sw.Elapsed); } static void TestRobustness() { var sw = new Stopwatch(); var parallelism = Environment.ProcessorCount; var maxProgramSizeLimit = 1024; var partitionSize = 100000; var execCounters = new long[parallelism]; var config = new PushConfiguration { EvalPushLimit = 1024, MaxProgramLength = 1024 }; config.DisableStack(StackTypes.Exec); config.DisableStack(StackTypes.Code); config.DisableStack(StackTypes.Float); var errors = config.EnabledExpressions.Where( name => { var type = ExpressionTable.NameToTypeTable[name]; var attribute = ExpressionTable.TypeToAttributeTable[type]; return attribute.StackType == StackTypes.Exec || attribute.AdditionalStackDependencies.HasFlag(StackTypes.Exec) || attribute.StackType == StackTypes.Code || attribute.AdditionalStackDependencies.HasFlag(StackTypes.Code) || attribute.StackType == StackTypes.Float || attribute.AdditionalStackDependencies.HasFlag(StackTypes.Float); }); var pool = new PushInterpreterPool(config); sw.Start(); Parallel.For(0, parallelism, i => { var random = new FastRandom(1337); using (var interpreter = pool.Create(random)) { for (var j = 0; j < partitionSize; j++) { var program = LinearCodeGenerator.RandomProgram(maxProgramSizeLimit, random, config); interpreter.Run(program); execCounters[i] += interpreter.ExecCounter; interpreter.Reset(); } } }); sw.Stop(); Console.WriteLine("ExecCount: {0}", execCounters.Sum()); Console.WriteLine("Duration: {0}", sw.Elapsed); } static void TestPool() { var pool = new PushInterpreterPool(); var normal = new PushInterpreter(); int id; using (var interpreter = pool.Create()) { interpreter.Run("( 1 2 INTEGER.+ )"); id = interpreter.GetHashCode(); if (id == normal.GetHashCode()) Console.WriteLine("equal 1"); } using (var interpreter = pool.Create()) using (var interpreter2 = pool.Create()) { interpreter.Run("( 1 2 INTEGER.+ )"); if (id == interpreter.GetHashCode()) Console.WriteLine("equal 2"); if (id == interpreter2.GetHashCode()) Console.WriteLine("equal 3"); } } static void TestPoolPerformance() { var sw = new Stopwatch(); var iterations = 100000000; sw.Start(); for (var i = 0; i < iterations; i++) { var interpreter = new PushInterpreter(); interpreter.ClearStacks(); } sw.Stop(); Console.WriteLine(sw.Elapsed); var pool = new PushInterpreterPool(); sw.Restart(); for (var i = 0; i < iterations; i++) { using (var interpreter = pool.Create()) { interpreter.ClearStacks(); } } sw.Stop(); Console.WriteLine(sw.Elapsed); } static void TestSimplifier() { var program = PushParser.ParseProgram("( 5 ( INTEGER.DUP FLOAT.+ FLOAT.- ) ( EXEC.DO ( EXEC.IF ) EXEC.Y ) INTEGER.+ )"); var pool = new PushInterpreterPool(); var random = new FastRandom(1337); var randomProg = LinearCodeGenerator.RandomProgram(4096 * 4, random); // 53 Func evaluator = prog => { using (var interpreter = pool.Create(random)) { interpreter.Run(prog); return interpreter.IntegerStack.IsEmpty ? double.MaxValue : Math.Abs(interpreter.IntegerStack.Top - 10); } }; var simplerProgram = Simplifier.Simplify(program, pool.PushConfiguration, evaluator); Console.WriteLine(simplerProgram); } } [Serializable] class Person : IPooledObject { public string Name { get; set; } public int Age { get; set; } public void Init() { } public void Reset() { Age = default(int); Name = null; } } }