Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/HeuristicLab.Problems.ProgramSynthesis.csproj
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/HeuristicLab.Problems.ProgramSynthesis.csproj	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/HeuristicLab.Problems.ProgramSynthesis.csproj	(revision 14746)
@@ -117,7 +117,6 @@
     <Compile Include="Push\Creator\PointsBasedPushProgramCreator.cs" />
     <Compile Include="Push\Data\List\SkipList.cs" />
-    <Compile Include="Push\Data\Pool\ManagedPool.cs" />
+    <Compile Include="Push\Data\Pool\ManagedPoolProvider.cs" />
     <Compile Include="Push\Data\Pool\ObjectPool.cs" />
-    <Compile Include="Push\Data\Pool\PoolContainer.cs" />
     <Compile Include="Push\Exporter\Exporter.cs" />
     <Compile Include="Push\Expressions\BooleanExpressions.cs" />
Index: anches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPool.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPool.cs	(revision 14745)
+++ 	(revision )
@@ -1,53 +1,0 @@
-﻿using System.Collections.Generic;
-
-namespace HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool {
-  using System;
-  using System.Collections.Concurrent;
-  using System.Linq;
-
-  public class ManagedPool<T> : IDisposable where T : class {
-
-    private static readonly ConcurrentStack<LinkedList<T>> Pool = new ConcurrentStack<LinkedList<T>>();
-    private readonly Func<T> Factory;
-    public readonly int PartitionSize;
-
-    private readonly IList<LinkedList<T>> partitions = new List<LinkedList<T>>();
-    private LinkedList<T> currentPartition;
-    private LinkedListNode<T> currentNode;
-
-    public ManagedPool(int partitionSize, Func<T> factory) {
-      PartitionSize = partitionSize;
-      Factory = factory;
-    }
-
-    public T Get() {
-      if (currentPartition == null || currentPartition.Count == PartitionSize) {
-        currentPartition = GetPartition();
-        currentNode = currentPartition.First;
-
-        partitions.Add(currentPartition);
-      }
-
-      T entry = null;
-      if (currentNode == null) {
-        entry = Factory();
-        currentPartition.AddLast(entry);
-      } else {
-        entry = currentNode.Value;
-        currentNode = currentNode.Next;
-      }
-
-      return entry;
-    }
-
-    private LinkedList<T> GetPartition() {
-      LinkedList<T> partition;
-
-      return Pool.TryPop(out partition) ? partition : new LinkedList<T>();
-    }
-
-    public void Dispose() {
-      Pool.PushRange(partitions.ToArray());
-    }
-  }
-}
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPoolProvider.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPoolProvider.cs	(revision 14746)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPoolProvider.cs	(revision 14746)
@@ -0,0 +1,96 @@
+﻿using System.Collections.Generic;
+
+namespace HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool {
+  using System;
+  using System.Collections.Concurrent;
+  using System.IO;
+  using System.Linq;
+  using System.Runtime.Serialization.Formatters.Binary;
+
+  public interface IManagedPool<T> : IDisposable where T : class {
+    T Get();
+  }
+
+  public class ManagedPoolProvider<T> where T : class {
+    private readonly ConcurrentStack<T[]> partitions = new ConcurrentStack<T[]>();
+    private readonly ObjectPool<IManagedPool<T>> managedPools;
+    private T[] DummyPartition;
+
+    public readonly int PartitionSize;
+    public readonly int MaxParitionCount;
+    public const int DefaultMaxInstanceCount = 65536;
+
+    public ManagedPoolProvider(int partitionSize, int maxPartitionCount = -1) {
+      PartitionSize = partitionSize;
+
+      if (maxPartitionCount <= 0) {
+        MaxParitionCount = DefaultMaxInstanceCount / PartitionSize;
+      }
+
+      managedPools = new ObjectPool<IManagedPool<T>>(() => new ManagedPool2<T>(this));
+    }
+
+    public void InitDummyPartition(Func<T> factory) {
+      DummyPartition = new T[PartitionSize];
+
+      for (var i = 0; i < PartitionSize; i++) {
+        DummyPartition[i] = factory();
+      }
+    }
+
+    public int InstanceCount { get { return partitions.Count * PartitionSize; } }
+
+    public void ReleasePartitions(params T[][] partition) {
+      if (partitions.Count <= MaxParitionCount && partition.Length > 0)
+        partitions.PushRange(partition);
+    }
+
+    private T[] GetPartition() {
+      T[] partition;
+      return partitions.TryPop(out partition) ? partition : DeepArrayCopy(DummyPartition);
+    }
+
+    private readonly BinaryFormatter binaryFormatter = new BinaryFormatter();
+    private T[] DeepArrayCopy(object objectToCopy) {
+      using (var memoryStream = new MemoryStream()) {
+        binaryFormatter.Serialize(memoryStream, objectToCopy);
+        memoryStream.Seek(0, SeekOrigin.Begin);
+
+        return (T[])binaryFormatter.Deserialize(memoryStream);
+      }
+    }
+
+    public IManagedPool<T> CreatePool() {
+      return managedPools.Allocate();
+    }
+
+    private class ManagedPool2<T> : IManagedPool<T> where T : class {
+      private readonly ManagedPoolProvider<T> provider;
+      private readonly IList<T[]> partitions = new List<T[]>();
+      private T[] currentPartition;
+      private int entryIndex;
+
+      public ManagedPool2(ManagedPoolProvider<T> provider) {
+        this.provider = provider;
+        entryIndex = provider.PartitionSize;
+      }
+
+      public T Get() {
+        if (entryIndex == provider.PartitionSize) {
+          currentPartition = provider.GetPartition();
+          partitions.Add(currentPartition);
+          entryIndex = 0;
+        }
+
+        return currentPartition[entryIndex++];
+      }
+
+      public void Dispose() {
+        provider.ReleasePartitions(partitions.ToArray());
+        partitions.Clear();
+        entryIndex = provider.PartitionSize;
+        provider.managedPools.Free(this);
+      }
+    }
+  }
+}
Index: anches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/PoolContainer.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/PoolContainer.cs	(revision 14745)
+++ 	(revision )
@@ -1,9 +1,0 @@
-﻿//namespace HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool {
-//  using System.Threading;
-
-//  using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
-
-//  internal static class PoolContainer {
-//    public static readonly ThreadLocal<ManagedPool<PushProgram>> PushProgramPool = new ThreadLocal<ManagedPool<PushProgram>>(() => new ManagedPool<PushProgram>(256, () => new PushProgram()));
-//  }
-//}
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/CodeExpressions.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/CodeExpressions.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/CodeExpressions.cs	(revision 14746)
@@ -108,58 +108,41 @@
       var second = interpreter.CodeStack.Top;
 
-      var isFirstList = first.CanExpand;
-      var isSecondList = second.CanExpand;
-
-      Expression[] result = null;
+      var isFirstList = first.IsProgram;
+      var isSecondList = second.IsProgram;
+
+      PushProgram result;
 
       if (isFirstList) {
-        var expand1 = first as PushProgram;
+        var program1 = first as PushProgram;
 
         if (isSecondList) {
-          var expand2 = second as PushProgram;
-          var size = expand2.State.Length + expand1.State.Length;
+          var program2 = second as PushProgram;
+          var size = program2.Expressions.Count + program1.Expressions.Count;
 
           // if size > maxPointsInProgram this expressions results in a NOOP
           if (size > interpreter.Configuration.MaxPointsInProgram) return false;
 
-          result = new Expression[size];
-
-          Array.Copy(expand2.State, result, expand2.State.Length);
-          Array.Copy(
-              expand1.State,
-              0,
-              result,
-              expand2.State.Length,
-              expand1.State.Length);
+          result = PushProgram.Merge(interpreter.PushProgramPool, program2, program1);
         } else {
-          var size = expand1.State.Length + 1;
+          var size = program1.Expressions.Count + 1;
 
           // if size > maxPointsInProgram this expressions results in a NOOP
           if (size > interpreter.Configuration.MaxPointsInProgram) return false;
 
-          result = new Expression[size];
-          result[0] = second;
-
-          Array.Copy(expand1.State, 0, result, 1, expand1.State.Length);
+          result = PushProgram.Merge(interpreter.PushProgramPool, second, program1);
         }
       } else if (isSecondList) {
-        var expand2 = second as PushProgram;
-
-        var size = expand2.State.Length + 1;
+        var program2 = second as PushProgram;
+        var size = program2.Expressions.Count + 1;
 
         // if size > maxPointsInProgram this expressions results in a NOOP
         if (size > interpreter.Configuration.MaxPointsInProgram) return false;
 
-        result = new Expression[size];
-        result[0] = first;
-
-        Array.Copy(expand2.State as Expression[], 0, result, 1, expand2.State.Length);
+        result = PushProgram.Merge(interpreter.PushProgramPool, first, program2);
       } else {
-        result = new[] { second, first };
+        result = PushProgram.Create(interpreter.PushProgramPool, second, first);
       }
 
-      var expression = new PushProgram(result);
-
-      interpreter.CodeStack.SetTop(expression);
+      interpreter.CodeStack.SetTop(result);
 
       return true;
@@ -177,5 +160,5 @@
 
       var expression = interpreter.CodeStack.Pop();
-      var isExpandExpression = expression.CanExpand;
+      var isExpandExpression = expression.IsProgram;
 
       interpreter.BooleanStack.Push(!isExpandExpression);
@@ -199,5 +182,5 @@
 
       if (expand.IsEmpty) return false;
-      var first = expand.State[expand.State.Length - 1];
+      var first = expand.Expressions[expand.Expressions.Count - 1];
 
       interpreter.CodeStack.SetTop(first);
@@ -217,22 +200,18 @@
       if (interpreter.CodeStack.Count == 0) return false;
 
-      PushProgram expandExpression;
+      PushProgram result;
       var top = interpreter.CodeStack.Top;
 
-      if (top.CanExpand) {
-        var expand = (PushProgram)top;
-
-        if (expand.IsEmpty) return false;
-        var length = expand.State.Length - 1;
-        var newExpressions = new Expression[length];
-
-        Array.Copy((Expression[])expand.State, 0, newExpressions, 0, length);
-
-        expandExpression = new PushProgram(newExpressions);
+      if (top.IsProgram) {
+        var program = (PushProgram)top;
+
+        if (program.IsEmpty) return false;
+
+        result = program.Copy(interpreter.PushProgramPool, 0, program.Expressions.Count - 1);
       } else {
-        expandExpression = PushProgram.Empty;
+        result = PushProgram.Empty;
       }
 
-      interpreter.CodeStack.SetTop(expandExpression);
+      interpreter.CodeStack.SetTop(result);
       return true;
     }
@@ -252,7 +231,7 @@
       PushProgram result;
 
-      if (interpreter.CodeStack.Top.CanExpand) {
+      if (interpreter.CodeStack.Top.IsProgram) {
         var first = (PushProgram)interpreter.CodeStack.Pop();
-        var size = first.State.Length + 1;
+        var size = first.Expressions.Count + 1;
 
         if (size > interpreter.Configuration.MaxPointsInProgram) return false;
@@ -260,10 +239,10 @@
         var expressions = new Expression[size];
 
-        expressions[first.State.Length] = interpreter.CodeStack.Top;
-        Array.Copy(first.State as Expression[], expressions, first.State.Length);
-
-        result = new PushProgram(expressions);
+        first.CopyExpressionsTo(expressions);
+        expressions[first.Expressions.Count] = interpreter.CodeStack.Top;
+
+        result = PushProgram.Create(interpreter.PushProgramPool, expressions);
       } else {
-        result = new PushProgram(interpreter.CodeStack.Pop(), interpreter.CodeStack.Top);
+        result = PushProgram.Create(interpreter.PushProgramPool, interpreter.CodeStack.Top);
       }
 
@@ -303,5 +282,5 @@
 
       var subContainer =
-          current.State.Where(e => e.CanExpand)
+          current.Expressions.Where(e => e.IsProgram)
               .Select(e => GetContainer(e as PushProgram, target))
               .Where(e => e != null);
@@ -309,6 +288,6 @@
       var execExpandExpressions = subContainer as IList<PushProgram> ?? subContainer.ToList();
       return execExpandExpressions.Any()
-          ? execExpandExpressions.OrderBy(c => c.State.Length).LastOrDefault()
-          : current.State.Contains(target)
+          ? execExpandExpressions.OrderBy(c => c.Expressions.Count).LastOrDefault()
+          : current.Expressions.Contains(target)
               ? current
               : null;
@@ -324,10 +303,10 @@
     public override bool Eval(IPushInterpreter interpreter) {
       if (interpreter.CodeStack.Count < 2 ||
-         !interpreter.CodeStack[interpreter.CodeStack.Count - 2].CanExpand)
+         !interpreter.CodeStack[interpreter.CodeStack.Count - 2].IsProgram)
         return false;
 
       var values = interpreter.CodeStack.Pop(2);
       var second = (PushProgram)values[0];
-      var contains = second.State.Contains(values[1]);
+      var contains = second.Expressions.Contains(values[1]);
 
       interpreter.BooleanStack.Push(contains);
@@ -413,9 +392,10 @@
 
     private void DetermineUniqueItems(Expression source, IDictionary<int, int> items) {
-      if (source.CanExpand) {
-        var expand = source as PushProgram;
-
-        foreach (var e in expand.State) {
-          var id = e.GetHashCode();
+      if (source.IsProgram) {
+        var program = source as PushProgram;
+        var expressions = program.Expressions;
+
+        for (var i = 0; i < expressions.Count; i++) {
+          var id = expressions[i].GetHashCode();
           if (!items.ContainsKey(id)) items.Add(id, 1);
           else items[id]++;
@@ -442,5 +422,5 @@
       if (interpreter.IntegerStack.Count == 0 ||
           interpreter.CodeStack.Count == 0 ||
-          !interpreter.CodeStack.Top.CanExpand)
+          !interpreter.CodeStack.Top.IsProgram)
         return false;
 
@@ -532,5 +512,5 @@
       if (interpreter.IntegerStack.Count == 0 ||
           interpreter.CodeStack.Count < 2 ||
-          !interpreter.CodeStack.Top.CanExpand)
+          !interpreter.CodeStack.Top.IsProgram)
         return false;
 
@@ -540,10 +520,10 @@
 
       Expression[] newExpressions;
-      if (target.State.Length > 0) {
-        index = target.State.Length - 1 - Math.Abs(index % target.State.Length);
+      if (!target.IsEmpty) {
+        index = target.Expressions.Count - 1 - Math.Abs(index % target.Expressions.Count);
 
         newExpressions = target.CopyExpressions();
-        newExpressions[index] = source.CanExpand
-            ? ((PushProgram)source).Copy()
+        newExpressions[index] = source.IsProgram
+            ? ((PushProgram)source).Copy(interpreter.PushProgramPool)
             : source;
       } else {
@@ -551,5 +531,5 @@
       }
 
-      var result = new PushProgram(newExpressions);
+      var result = PushProgram.Create(interpreter.PushProgramPool, newExpressions);
       interpreter.CodeStack.SetTop(result);
 
@@ -572,6 +552,6 @@
       var count = 1;
 
-      if (expression.CanExpand)
-        count = ((PushProgram)expression).State.Length;
+      if (expression.IsProgram)
+        count = ((PushProgram)expression).Expressions.Count;
 
       interpreter.IntegerStack.Push(count);
@@ -591,5 +571,5 @@
       var first = interpreter.CodeStack.Pop();
       var second = interpreter.CodeStack.Top;
-      var expandExpression = new PushProgram(second, first);
+      var expandExpression = PushProgram.Create(interpreter.PushProgramPool, second, first);
 
       interpreter.CodeStack.SetTop(expandExpression);
@@ -610,6 +590,6 @@
       var expressions = interpreter.CodeStack.Pop(2);
 
-      var contains = expressions[1].CanExpand
-          ? ((PushProgram)expressions[1]).State.Contains(expressions[0])
+      var contains = expressions[1].IsProgram
+          ? ((PushProgram)expressions[1]).Expressions.Contains(expressions[0])
           : expressions[1].Equals(expressions[0]);
 
@@ -635,5 +615,5 @@
       Expression nthExpression;
 
-      if (expression.CanExpand) {
+      if (expression.IsProgram) {
         var subExpression = (PushProgram)expression;
 
@@ -641,8 +621,7 @@
           nthExpression = PushProgram.Empty;
         } else {
-          var index = (int)(subExpression.State.Length - 1 -
-                             Math.Abs(n % subExpression.State.Length));
-
-          nthExpression = subExpression.State[index];
+          var index = (int)(subExpression.Expressions.Count - 1 - Math.Abs(n % subExpression.Expressions.Count));
+
+          nthExpression = subExpression.Expressions[index];
         }
       } else {
@@ -674,11 +653,11 @@
       Expression nthExpression;
 
-      if (expression.CanExpand) {
-        var subExpressions = ((PushProgram)expression).State;
-
-        if (subExpressions.Length < 2) {
+      if (expression.IsProgram) {
+        var subExpressions = ((PushProgram)expression).Expressions;
+
+        if (subExpressions.Count < 2) {
           nthExpression = PushProgram.Empty;
         } else {
-          var index = (int)(subExpressions.Length - 2 - Math.Abs(n % (subExpressions.Length - 1)));
+          var index = (int)(subExpressions.Count - 2 - Math.Abs(n % (subExpressions.Count - 1)));
 
           nthExpression = subExpressions[index];
@@ -723,8 +702,7 @@
 
       var position = -1;
-      if (first.CanExpand) {
-        var expand = (PushProgram)first;
-        position = expand.State.Length - 1
-                   - Array.FindIndex((Expression[])expand.State, e => e.Equals(second));
+      if (first.IsProgram) {
+        var program = (PushProgram)first;
+        position = program.Expressions.Count - 1 - program.IndexOf(second);
       } else if (first.Equals(second)) {
         position = 0;
@@ -747,6 +725,6 @@
 
       var expression = interpreter.CodeStack.Pop();
-      var points = expression.CanExpand
-          ? ((PushProgram)expression).State.Length
+      var points = expression.IsProgram
+          ? ((PushProgram)expression).Expressions.Count
           : 1;
 
@@ -773,13 +751,14 @@
       var second = expressions[0];
       var first = expressions[1] as PushProgram;
-      var newExpressions = new Expression[first.State.Length];
-
-      for (var i = 0; i < first.State.Length; i++)
-        newExpressions[i] = first.State[i].Equals(third)
+      var firstExpressions = first.Expressions;
+      var newExpressions = new Expression[firstExpressions.Count];
+
+      for (var i = 0; i < firstExpressions.Count; i++)
+        newExpressions[i] = firstExpressions[i].Equals(third)
             ? second
             /* no cloning needed here because first is removed and therefore newExpression is the only container of sub expressions */
-            : first.State[i];
-
-      var result = new PushProgram(newExpressions);
+            : firstExpressions[i];
+
+      var result = PushProgram.Create(interpreter.PushProgramPool, newExpressions);
 
       interpreter.CodeStack.SetTop(result);
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/ExecExpressions.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/ExecExpressions.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/ExecExpressions.cs	(revision 14746)
@@ -41,6 +41,5 @@
       var top = interpreter.ExecStack.Top;
       var execYExpression = ExpressionTable.GetStatelessExpression<ExecYExpression>();
-
-      var result = new PushProgram(top, execYExpression);
+      var result = PushProgram.Create(interpreter.PushProgramPool, top, execYExpression);
 
       interpreter.ExecStack.SetTop(result);
@@ -81,5 +80,5 @@
       var c = interpreter.ExecStack.Top;
 
-      var newTop = new PushProgram(c, b);
+      var newTop = PushProgram.Create(interpreter.PushProgramPool, c, b);
 
       interpreter.ExecStack.SetTop(newTop);
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/Expression.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/Expression.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/Expression.cs	(revision 14746)
@@ -7,6 +7,7 @@
   using Interpreter;
 
+  [Serializable]
   public abstract class Expression {
-    public bool CanExpand { get { return this.GetType() == typeof(PushProgram); } }
+    public bool IsProgram { get { return this.GetType() == typeof(PushProgram); } }
 
     public static readonly IReadOnlyCollection<Expression> EmptyContainer = new Expression[0];
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/ExpressionTable.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/ExpressionTable.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/ExpressionTable.cs	(revision 14746)
@@ -5,4 +5,5 @@
 
   using HeuristicLab.Problems.ProgramSynthesis.Push.Attributes;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Stack;
 
@@ -123,5 +124,5 @@
     }
 
-    public static PushProgram GetProgram(int[] index) {
+    public static PushProgram GetProgram(IManagedPool<PushProgram> pool, int[] index) {
       var expressions = new Expression[index.Length];
 
@@ -130,5 +131,5 @@
       }
 
-      return new PushProgram(expressions);
+      return PushProgram.Create(pool, expressions);
     }
 
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.bk.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.bk.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.bk.cs	(revision 14746)
@@ -88,5 +88,5 @@
 //    public IEnumerable<Expression> DepthFirst() {
 //      foreach (var expr in this.Expressions) {
-//        if (expr.CanExpand) {
+//        if (expr.IsProgram) {
 //          var expandExpr = (PushProgram)expr;
 
@@ -114,5 +114,5 @@
 
 //    private int CalcDepth() {
-//      //var subExpressions = Expressions.Where(e => e.CanExpand);
+//      //var subExpressions = Expressions.Where(e => e.IsProgram);
 //      //var depth = subExpressions.Any()
 //      //    ? subExpressions.Select(e => e as PushProgram).Max(e => e.State.Depth) + 1
@@ -124,5 +124,5 @@
 //      for (var i = 0; i < Expressions.Count; i++) {
 //        var expression = Expressions[i];
-//        if (!expression.CanExpand) continue;
+//        if (!expression.IsProgram) continue;
 //        var expandExpression = (PushProgram)expression;
 
@@ -151,5 +151,5 @@
 //        local_treeIndex[i] = next;
 
-//        if (subExpression.CanExpand) {
+//        if (subExpression.IsProgram) {
 //          next += ((PushProgram)subExpression).State.TotalCount;
 //        } else {
@@ -184,5 +184,5 @@
 
 //      for (var i = 0; i < current.State.Expressions.Count; i++) {
-//        if (current.State.Expressions[i].CanExpand)
+//        if (current.State.Expressions[i].IsProgram)
 //          continue;
 
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/PushProgram.cs	(revision 14746)
@@ -6,7 +6,11 @@
   using System.Diagnostics;
 
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
+
   using Interpreter;
 
-  public class PushProgram : StatefulExpression<Expression[]> {
+  [Serializable]
+  public sealed class PushProgram : Expression {
+    private static readonly Expression[] EmptyExpressions = new Expression[0];
     public static readonly PushProgram Empty = new PushProgram();
 
@@ -17,12 +21,71 @@
     private const string Delimiter = " ";
 
-    public readonly bool IsEmpty;
-
-    public PushProgram(params Expression[] state) : base(state) {
-      IsEmpty = state.Length == 0;
-    }
-
-    public PushProgram(IEnumerable<Expression> state) : this(state.ToArray()) {
-      // TODO: lazy evaluation of ToArray()
+    private Expression[] expressions;
+
+    public PushProgram() : this(EmptyExpressions) {
+    }
+
+    public PushProgram(Expression[] expressions) {
+      this.expressions = expressions;
+    }
+
+    public bool IsEmpty { get { return Count == 0; } }
+    public int Count { get { return expressions.Length; } }
+
+    public IReadOnlyList<Expression> Expressions { get { return this.expressions; } }
+
+    public static PushProgram Create(IManagedPool<PushProgram> pool, params Expression[] expressions) {
+      var program = pool.Get();
+
+      program.expressions = expressions;
+      program.Reset();
+
+      return program;
+    }
+
+    private void Reset() {
+      stringRepresentation = null;
+      depth = null;
+      treeIndex = null;
+      hashCode = null;
+    }
+
+    public static PushProgram Merge(IManagedPool<PushProgram> pool, PushProgram first, Expression second) {
+      var program = pool.Get();
+
+      program.Reset();
+      program.expressions = new Expression[first.Expressions.Count + 1];
+      first.CopyExpressionsTo(program.expressions);
+      program.expressions[0] = first;
+
+      return program;
+    }
+
+    public static PushProgram Merge(IManagedPool<PushProgram> pool, Expression first, PushProgram second) {
+      var program = pool.Get();
+
+      program.Reset();
+
+      program.expressions = new Expression[second.Expressions.Count + 1];
+      program.expressions[0] = first;
+      second.CopyExpressionsTo(program.expressions, 0, 1, second.Count);
+
+      return program;
+    }
+
+    public static PushProgram Merge(IManagedPool<PushProgram> pool, PushProgram first, PushProgram second) {
+      var program = pool.Get();
+
+      program.Reset();
+      program.expressions = new Expression[first.Count + second.Count];
+
+      first.CopyExpressionsTo(program.expressions);
+      second.CopyExpressionsTo(program.expressions, 0, first.Count, second.Count);
+
+      return program;
+    }
+
+    public int IndexOf(Expression expression) {
+      return Array.IndexOf(this.expressions, expression);
     }
 
@@ -32,17 +95,17 @@
       get
       {
-        if (string.IsNullOrEmpty(stringRepresentation))
-          stringRepresentation = BuildString();
+        if (stringRepresentation == null) stringRepresentation = BuildString();
         return stringRepresentation;
       }
     }
 
-    private int depth = -1;
+
+    private int? depth;
     public int Depth
     {
       get
       {
-        if (depth == -1) depth = CalcDepth();
-        return depth;
+        if (depth == null) depth = CalcDepth();
+        return depth.Value;
       }
     }
@@ -53,36 +116,29 @@
       get
       {
-        return treeIndex ?? (treeIndex = BuildTreeIndex());
-      }
-    }
-
-    private int hashCode;
-    private int HashCode
-    {
-      get
-      {
-        if (hashCode == default(int)) hashCode = HashExpressions();
-        return hashCode;
-      }
+        if (treeIndex == null) treeIndex = BuildTreeIndex();
+        return treeIndex;
+      }
+    }
+
+    private int? hashCode;
+    public override int GetHashCode() {
+      if (hashCode == null) hashCode = HashExpressions();
+      return hashCode.Value;
     }
 
     //public PushProgram Copy() {
     //  // as the empty list is a static stateless expression, no copy required
-    //  return ReferenceEquals(this, Empty) || this.State.IsEmpty
+    //  return ReferenceEquals(this, Empty) || this.expressions.IsEmpty
     //    ? Empty
-    //    : new PushProgram(this.State.Copy());
+    //    : new PushProgram(this.expressions.Copy());
     //}
 
     public override bool Eval(IPushInterpreter interpreter) {
-      interpreter.ExecStack.Push(this.State);
+      interpreter.ExecStack.Push(this.expressions);
       return true;
     }
 
-    public override int GetHashCode() {
-      return HashCode;
-    }
-
     public override string ToString() {
-      return this.StringRepresentation;
+      return StringRepresentation;
     }
 
@@ -103,6 +159,6 @@
 
     public IEnumerable<Expression> DepthFirst() {
-      foreach (var expr in this.State) {
-        if (expr.CanExpand) {
+      foreach (var expr in this.expressions) {
+        if (expr.IsProgram) {
           var expandExpr = (PushProgram)expr;
 
@@ -114,5 +170,7 @@
 
     public PushProgram Copy() {
-      return IsEmpty ? this : new PushProgram(State) {
+      if (IsEmpty) return this;
+
+      var program = new PushProgram(this.expressions) {
         stringRepresentation = this.stringRepresentation,
         hashCode = this.hashCode,
@@ -120,21 +178,65 @@
         treeIndex = this.treeIndex
       };
-    }
-
-    public Expression[] CopyExpressions()
-    {
-      if (IsEmpty) return Empty.State;
-
-      var copy = new Expression[State.Length];
-      State.CopyTo(copy, 0);
+
+      return program;
+    }
+
+    public PushProgram Copy(IManagedPool<PushProgram> pool) {
+      if (IsEmpty) return this;
+
+      var program = pool.Get();
+      program.expressions = this.expressions;
+      program.stringRepresentation = stringRepresentation;
+      program.hashCode = hashCode;
+      program.depth = depth;
+      program.treeIndex = treeIndex;
+
+      return program;
+    }
+
+    public PushProgram Copy(IManagedPool<PushProgram> pool, int startIndex, int length) {
+      if (IsEmpty) return this;
+
+      var program = pool.Get();
+      program.expressions = CopyExpressions(startIndex, length);
+
+      program.Reset();
+
+      return program;
+    }
+
+    public Expression[] CopyExpressions() {
+      return CopyExpressions(Count);
+    }
+
+    public Expression[] CopyExpressions(int length) {
+      if (IsEmpty) return EmptyExpressions;
+
+      var copy = new Expression[length];
+      this.expressions.CopyTo(copy, 0);
 
       return copy;
+    }
+
+    public Expression[] CopyExpressions(int startIndex, int length) {
+      if (IsEmpty) return EmptyExpressions;
+
+      var copy = new Expression[length];
+      CopyExpressionsTo(copy, startIndex, 0, length);
+
+      return copy;
+    }
+
+    public void CopyExpressionsTo(Expression[] destination, int? sourceIndex = null, int? destinationIndex = null, int? length = null) {
+      if (IsEmpty) return;
+
+      Array.Copy(this.expressions, sourceIndex ?? 0, destination, destinationIndex ?? 0, length ?? Count);
     }
 
     private int CalcDepth() {
       var maxDepth = 1;
-      for (var i = 0; i < State.Length; i++) {
-        var expression = State[i];
-        if (!expression.CanExpand) continue;
+      for (var i = 0; i < Count; i++) {
+        var expression = this.expressions[i];
+        if (!expression.IsProgram) continue;
         var expandExpression = (PushProgram)expression;
 
@@ -149,19 +251,19 @@
       // prevent too big string
       return this.TotalCount > 50
-        ? PrefixReduced + this.State.Length + PostfixReduced
-        : Prefix + string.Join(Delimiter, this.State.Where(e => !string.IsNullOrWhiteSpace(e.StringRepresentation))) + Postfix;
+        ? PrefixReduced + this.Count + PostfixReduced
+        : Prefix + string.Join(Delimiter, this.expressions.Where(e => !string.IsNullOrWhiteSpace(e.StringRepresentation))) + Postfix;
     }
 
     private int[] BuildTreeIndex() {
-      var local_treeIndex = new int[State.Length];
+      var local_treeIndex = new int[Count];
 
       var next = 1;
 
-      for (var i = State.Length - 1; i >= 0; i--) {
-        var subExpression = State[i];
+      for (var i = Count - 1; i >= 0; i--) {
+        var subExpression = this.expressions[i];
 
         local_treeIndex[i] = next;
 
-        if (subExpression.CanExpand) {
+        if (subExpression.IsProgram) {
           next += ((PushProgram)subExpression).TotalCount;
         } else {
@@ -176,6 +278,6 @@
       var hash = 19 * 31 + this.GetType().FullName.GetHashCode();
 
-      for (var i = 0; i < State.Length; i++) {
-        hash = hash * 31 + State[i].GetHashCode();
+      for (var i = 0; i < Count; i++) {
+        hash = hash * 31 + this.expressions[i].GetHashCode();
       }
 
@@ -195,9 +297,9 @@
       }
 
-      for (var i = 0; i < current.State.Length; i++) {
-        if (current.State[i].CanExpand)
+      for (var i = 0; i < current.Count; i++) {
+        if (current.expressions[i].IsProgram)
           continue;
 
-        var subExpression = current.State[i] as PushProgram;
+        var subExpression = current.expressions[i] as PushProgram;
 
         if (ReferenceEquals(target, subExpression)) {
@@ -231,5 +333,5 @@
       if (index == 0) return resolver(parent, parent, this, 0, parentIndex);
 
-      var min = State.Length - 1;
+      var min = Count - 1;
       var max = 0;
       var mid = (min + max) / 2;
@@ -243,6 +345,6 @@
 
       return TreeIndex[mid] == index
-          ? resolver(parent, this, State[mid], mid, parentIndex)
-          : (State[mid + 1] as PushProgram).GetFromTree(index - TreeIndex[mid + 1], mid + 1,
+          ? resolver(parent, this, this.expressions[mid], mid, parentIndex)
+          : (this.expressions[mid + 1] as PushProgram).GetFromTree(index - TreeIndex[mid + 1], mid + 1,
               this, resolver);
     }
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/RandExpressions.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/RandExpressions.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/RandExpressions.cs	(revision 14746)
@@ -69,5 +69,6 @@
 
       var size = (int)(interpreter.IntegerStack.Pop() % interpreter.Configuration.MaxPointsInRandomExpression);
-      var program = CodeGenerator.RandomExpandExpression(
+      var program = CodeGenerator.RandomProgram(
+        interpreter.PushProgramPool,
         size,
         interpreter.Random,
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/StatefulExpression.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/StatefulExpression.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/StatefulExpression.cs	(revision 14746)
@@ -2,14 +2,5 @@
   public abstract class StatefulExpression<T> : Expression {
     public readonly T State;
-
-    private int hashCode;
-    private int HashCode
-    {
-      get
-      {
-        if (hashCode == default(int)) hashCode = CalcHashCode();
-        return hashCode;
-      }
-    }
+    private int? hashCode;
 
     protected StatefulExpression(T state) {
@@ -34,6 +25,18 @@
     }
 
+    public bool Equals(StatefulExpression<T> obj) {
+      if (ReferenceEquals(this, obj))
+        return true;
+
+      if (GetType() != obj.GetType())
+        return false;
+
+      return ReferenceEquals(State, obj.State) ||
+             GetHashCode() == obj.GetHashCode();
+    }
+
     public override int GetHashCode() {
-      return HashCode;
+      if (hashCode == null) hashCode = CalcHashCode();
+      return hashCode.Value;
     }
   }
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Generators/CodeGenerator.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Generators/CodeGenerator.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Generators/CodeGenerator.cs	(revision 14746)
@@ -5,4 +5,5 @@
   using HeuristicLab.Core;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
   using HeuristicLab.Random;
@@ -18,14 +19,8 @@
   public static class CodeGenerator {
 
-    public static PushProgram RandomProgram(int maxPoints, IRandom random = null, IReadonlyPushConfiguration pushGpConfiguration = null, IDictionary<string, Expression> customExpressions = null) {
+    public static PushProgram RandomProgram(IManagedPool<PushProgram> pool, int maxPoints, IRandom random = null, IReadonlyPushConfiguration pushGpConfiguration = null, IDictionary<string, Expression> customExpressions = null) {
       var code = RandomCode(maxPoints, random, pushGpConfiguration, customExpressions);
 
-      return new PushProgram(code.ToArray());
-    }
-
-    public static PushProgram RandomExpandExpression(int maxPoints, IRandom random = null, IReadonlyPushConfiguration pushGpConfiguration = null, IDictionary<string, Expression> customExpressions = null) {
-      var program = RandomProgram(maxPoints, random, pushGpConfiguration, customExpressions);
-
-      return new PushProgram(program);
+      return PushProgram.Create(pool, code.ToArray());
     }
 
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/IPushInterpreter.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/IPushInterpreter.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/IPushInterpreter.cs	(revision 14746)
@@ -7,4 +7,5 @@
 
   using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
 
   using Stack;
@@ -23,4 +24,6 @@
 
     IReadonlyPushConfiguration Configuration { get; }
+
+    IManagedPool<PushProgram> PushProgramPool { get; }
 
     bool IsNameQuoteFlagSet { get; set; }
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/PushInterpreter.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/PushInterpreter.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Interpreter/PushInterpreter.cs	(revision 14746)
@@ -2,4 +2,7 @@
   using System;
   using System.Collections.Generic;
+#if DEBUG
+  using System.Linq;
+#endif
   using System.Runtime.CompilerServices;
   using System.Threading;
@@ -7,4 +10,5 @@
   using HeuristicLab.Core;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Parser;
@@ -82,4 +86,6 @@
     }
 
+    public IManagedPool<PushProgram> PushProgramPool { get; set; }
+
     public IReadonlyPushConfiguration Configuration { get; protected set; }
 
@@ -249,8 +255,24 @@
     }
 
+#if DEBUG
+    private Expression last;
+    private bool DoStep() {
+      var expression = ExecStack.Pop();
+
+      if (ExecStack.Any(e => e == null)) {
+        throw new InvalidProgramException();
+      }
+
+      var succ = expression.Eval(this);
+      last = expression;
+
+      return succ;
+    }
+#else
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     private bool DoStep() {
       return ExecStack.Pop().Eval(this);
     }
+#endif
 
     private Task InterpretAsync() {
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushEncoding.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushEncoding.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushEncoding.cs	(revision 14746)
@@ -42,7 +42,13 @@
 
     public static PushProgram MapToPushProgram(this IntegerVector vector, IReadOnlyList<string> enabledExpressions) {
-      var expressions = vector
-        .Select(i => ExpressionTable.GetExpression(enabledExpressions[i]))
-        .ToArray();
+      //var expressions = vector
+      //  .Select(i => ExpressionTable.GetExpression(enabledExpressions[i]))
+      //  .ToArray();
+
+      var expressions = new Expression[vector.Length];
+      for (var i = 0; i < vector.Length; i++)
+      {
+        expressions[i] = ExpressionTable.GetExpression(enabledExpressions[vector[i]]);
+      }
 
       return new Expressions.PushProgram(expressions);
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushProblem.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushProblem.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Problem/PushProblem.cs	(revision 14746)
@@ -12,4 +12,6 @@
   using HeuristicLab.BenchmarkSuite;
   using HeuristicLab.Data;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
+
   using Instances;
   using Interpreter;
@@ -26,8 +28,12 @@
     private readonly PushConfiguration config;
     private PushInterpreterPool pool;
+    private ManagedPoolProvider<PushProgram> pushProgramPoolProvider;
 
     public PushProblem() {
       config = new PushConfiguration();
       pool = new PushInterpreterPool(config);
+
+      pushProgramPoolProvider = new ManagedPoolProvider<PushProgram>(1024);
+      pushProgramPoolProvider.InitDummyPartition(() => new PushProgram());
 
       InitEvents();
@@ -56,4 +62,7 @@
       pool = new PushInterpreterPool(config);
       Instructions = config;
+
+      pushProgramPoolProvider = new ManagedPoolProvider<PushProgram>(1024);
+      pushProgramPoolProvider.InitDummyPartition(() => new PushProgram());
 
       InitEvents();
@@ -404,12 +413,12 @@
 
     public override double Evaluate(Individual individual, IRandom random) {
+      if (DataBounds[0, 1] <= 0) return default(double);
 
       var program = individual.PushProgram(config.EnabledExpressions as IReadOnlyList<string>);
-      var expandExpression = new PushProgram(program);
-      var results = new List<double>();
+      var result = 0d;
 
       using (var interpreter = pool.GetInstance(random)) {
         for (var i = DataBounds[0, 0]; i < DataBounds[0, 1]; i++) {
-          var example = this.DataDescriptor.Examples[i];
+          var example = DataDescriptor.Examples[i];
 
           interpreter.BooleanStack.Push(example.InputBoolean);
@@ -417,16 +426,17 @@
           interpreter.FloatStack.Push(example.InputFloat);
 
-          interpreter.Run(expandExpression);
-
-          var diff = GetDiff(example.OutputInt, interpreter.IntegerStack, this.DataDescriptor.WorstResult, LongDiffer) +
-                     GetDiff(example.OutputFloat, interpreter.FloatStack, this.DataDescriptor.WorstResult, DoubleDiffer) +
-                     GetDiff(example.OutputBoolean, interpreter.BooleanStack, this.DataDescriptor.WorstResult, BooleanDiffer);
-
-          results.Add(diff);
+          using (interpreter.PushProgramPool = pushProgramPoolProvider.CreatePool()) {
+            interpreter.Run(program);
+          }
+
+          result += GetDiff(example.OutputInt, interpreter.IntegerStack, DataDescriptor.WorstResult, LongDiffer)
+                  + GetDiff(example.OutputFloat, interpreter.FloatStack, DataDescriptor.WorstResult, DoubleDiffer)
+                  + GetDiff(example.OutputBoolean, interpreter.BooleanStack, DataDescriptor.WorstResult, BooleanDiffer);
+
           interpreter.Clear();
         }
       }
 
-      return results.Count == 0 ? 0d : results.Average();
+      return result / DataBounds[0, 1];
     }
 
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Simplifier/RandomSimplifier.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Simplifier/RandomSimplifier.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Simplifier/RandomSimplifier.cs	(revision 14746)
@@ -1,58 +1,58 @@
-﻿namespace HeuristicLab.Problems.ProgramSynthesis.Push.Simplifier {
-  using System;
-  using HeuristicLab.Core;
-  using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
+﻿//namespace HeuristicLab.Problems.ProgramSynthesis.Push.Simplifier {
+//  using System;
+//  using HeuristicLab.Core;
+//  using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
 
-  public class RandomSimplifier : ISimplifier {
-    public int Trys { get; set; }
+//  public class RandomSimplifier : ISimplifier {
+//    public int Trys { get; set; }
 
-    public PushProgram Simplify(PushProgram program, IRandom random, Predicate<PushProgram> isBetter) {
+//    public PushProgram Simplify(PushProgram program, IRandom random, Predicate<PushProgram> isBetter) {
 
-      if (program.TotalCount == 1) {
-        return isBetter(PushProgram.Empty) ? PushProgram.Empty : program;
-      }
+//      if (program.TotalCount == 1) {
+//        return isBetter(PushProgram.Empty) ? PushProgram.Empty : program;
+//      }
 
-      var copy = program.Copy();
-      var maxTries = Math.Min(Trys, program.TotalCount - 2);
-      var successfulRemoves = 0;
+//      var copy = program.Copy();
+//      var maxTries = Math.Min(Trys, program.TotalCount - 2);
+//      var successfulRemoves = 0;
 
-      for (var i = 0; i < maxTries; i++) {
-        var rndIndex = random.Next(1, program.TotalCount - 1 - successfulRemoves);
-        var node = copy.GetFromTree(
-          rndIndex,
-          (super, parent, child, childIndex, parentIndex) => new {
-            Super = super,
-            Parent = parent,
-            ChildIndex = childIndex,
-            ParentIndex = parentIndex
-          });
+//      for (var i = 0; i < maxTries; i++) {
+//        var rndIndex = random.Next(1, program.TotalCount - 1 - successfulRemoves);
+//        var node = copy.GetFromTree(
+//          rndIndex,
+//          (super, parent, child, childIndex, parentIndex) => new {
+//            Super = super,
+//            Parent = parent,
+//            ChildIndex = childIndex,
+//            ParentIndex = parentIndex
+//          });
 
-        var oldParentExpressions = node.Parent.State;
-        var newParentExpressions = RemoveAt(oldParentExpressions, node.ChildIndex);
-        var newParent = new PushProgram(newParentExpressions);
+//        var oldParentExpressions = node.Parent.State;
+//        var newParentExpressions = RemoveAt(oldParentExpressions, node.ChildIndex);
+//        var newParent = new PushProgram(newParentExpressions);
 
-        var superExpressions = node.Super == null ? copy.State : node.Super.State;
-        superExpressions[node.ParentIndex] = newParent;
+//        var superExpressions = node.Super == null ? copy.State : node.Super.State;
+//        superExpressions[node.ParentIndex] = newParent;
 
-        if (isBetter(copy)) {
-          successfulRemoves++;
-        } else {
-          superExpressions[node.ParentIndex] = node.Parent;
-        }
-      }
+//        if (isBetter(copy)) {
+//          successfulRemoves++;
+//        } else {
+//          superExpressions[node.ParentIndex] = node.Parent;
+//        }
+//      }
 
-      return copy;
-    }
+//      return copy;
+//    }
 
-    private static T[] RemoveAt<T>(T[] source, int index) {
-      var dest = new T[source.Length - 1];
-      if (index > 0)
-        Array.Copy(source, 0, dest, 0, index);
+//    private static T[] RemoveAt<T>(T[] source, int index) {
+//      var dest = new T[source.Length - 1];
+//      if (index > 0)
+//        Array.Copy(source, 0, dest, 0, index);
 
-      if (index < source.Length - 1)
-        Array.Copy(source, index + 1, dest, index, source.Length - index - 1);
+//      if (index < source.Length - 1)
+//        Array.Copy(source, index + 1, dest, index, source.Length - index - 1);
 
-      return dest;
-    }
-  }
-}
+//      return dest;
+//    }
+//  }
+//}
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Tests/Benchmark/ProblemTests.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Tests/Benchmark/ProblemTests.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Tests/Benchmark/ProblemTests.cs	(revision 14746)
@@ -147,11 +147,18 @@
       var instance = new BenchmarkSuiteInstanceProvider();
       var data = instance.LoadData(descriptor);
+      var provider = new ManagedPoolProvider<PushProgram>(1024);
+      provider.InitDummyPartition(() => new PushProgram());
 
       Parallel.For(0, iterations, i => {
         var execCounter = 0;
-        var program = CodeGenerator.RandomExpandExpression(maxProgramSizeLimit, random);
+
+        var pushProgramPool = provider.CreatePool();
+        var program = CodeGenerator.RandomProgram(pushProgramPool, maxProgramSizeLimit, random);
+
         var results = new double[data.OriginalTrainingCount];
 
         using (var interpreter = pool.GetInstance(random)) {
+          interpreter.PushProgramPool = pushProgramPool;
+
           for (var j = 0; j < data.OriginalTrainingCount; j++) {
             var example = data.Examples[i];
@@ -162,8 +169,9 @@
 
             interpreter.Run(program);
-
-            var diff = GetDiff(example.OutputInt, interpreter.IntegerStack) +
-                       GetDiff(example.OutputFloat, interpreter.FloatStack) +
-                       GetDiff(example.OutputBoolean, interpreter.BooleanStack);
+            pushProgramPool.Dispose();
+
+            var diff = GetDiff(example.OutputInt, interpreter.IntegerStack)
+                       + GetDiff(example.OutputFloat, interpreter.FloatStack)
+                       + GetDiff(example.OutputBoolean, interpreter.BooleanStack);
 
             results[j] = diff;
@@ -171,4 +179,5 @@
             execCounter += interpreter.ExecCounter;
             interpreter.Clear();
+            pushProgramPool = provider.CreatePool();
           }
         }
Index: /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Tests/Interpreter/Expressions/StandardTests.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Tests/Interpreter/Expressions/StandardTests.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Tests/Interpreter/Expressions/StandardTests.cs	(revision 14746)
@@ -31,5 +31,5 @@
       Debug.WriteLine("Duplicates: ");
       foreach (var duplicate in duplicates)
-         Debug.WriteLine("Id: {0}, Expression: {1}", duplicate.Id, duplicate.Epxression);
+        Debug.WriteLine("Id: {0}, Expression: {1}", duplicate.Id, duplicate.Epxression);
 
       Assert.Fail();
@@ -75,6 +75,6 @@
       var clone = list2.Copy();
 
-      Assert.AreSame(list, clone.State.Last());
-      Assert.AreEqual(list, clone.State.Last());
+      Assert.AreSame(list, clone.Expressions.Last());
+      Assert.AreEqual(list, clone.Expressions.Last());
 
       Assert.AreNotSame(list2, clone);
Index: /branches/PushGP/HeuristicLab.PushGP/PushGP.Cli/Program.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/PushGP.Cli/Program.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/PushGP.Cli/Program.cs	(revision 14746)
@@ -6,9 +6,9 @@
 namespace HeuristicLab.Algorithms.PushGP.Cli {
   using HeuristicLab.Problems.ProgramSynthesis.Push.Configuration;
+  using HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Generators;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter;
   using HeuristicLab.Problems.ProgramSynthesis.Push.Parser;
-  using HeuristicLab.Problems.ProgramSynthesis.Push.Simplifier;
   using HeuristicLab.Random;
 
@@ -162,4 +162,7 @@
       };
 
+      var provider = new ManagedPoolProvider<PushProgram>(1024);
+      provider.InitDummyPartition(() => new PushProgram());
+
       var pool = new PushInterpreterPool(config);
 
@@ -169,7 +172,8 @@
         using (var interpreter = pool.GetInstance(random)) {
           for (var j = 0; j < partitionSize; j++) {
-            var program = CodeGenerator.RandomProgram(maxProgramSizeLimit, random, config);
-
-            interpreter.Run(program);
+            using (interpreter.PushProgramPool = provider.CreatePool()) {
+              var program = CodeGenerator.RandomProgram(interpreter.PushProgramPool, maxProgramSizeLimit, random, config);
+              interpreter.Run(program);
+            }
 
             execCounters[i] += interpreter.ExecCounter;
@@ -229,21 +233,21 @@
     }
 
-    static void TestSimplifier() {
-      var interpreter = new PushInterpreter();
-      var program = PushParser.Parse("( 5 INTEGER.DUP FLOAT.+ INTEGER.+ )") as PushProgram;
-      var simplifier = new RandomSimplifier { Trys = 10 };
-      var random = new FastRandom(1337);
-
-      var simplerProgram = simplifier.Simplify(
-        program,
-        random,
-        solution => {
-          interpreter.Clear();
-          interpreter.Run(solution);
-          return interpreter.IntegerStack.Top == 10;
-        });
-
-      Console.WriteLine(simplerProgram);
-    }
+    //static void TestSimplifier() {
+    //  var interpreter = new PushInterpreter();
+    //  var program = PushParser.Parse("( 5 INTEGER.DUP FLOAT.+ INTEGER.+ )") as PushProgram;
+    //  var simplifier = new RandomSimplifier { Trys = 10 };
+    //  var random = new FastRandom(1337);
+
+    //  var simplerProgram = simplifier.Simplify(
+    //    program,
+    //    random,
+    //    solution => {
+    //      interpreter.Clear();
+    //      interpreter.Run(solution);
+    //      return interpreter.IntegerStack.Top == 10;
+    //    });
+
+    //  Console.WriteLine(simplerProgram);
+    //}
   }
 }
Index: anches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/IManagedPool.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/IManagedPool.cs	(revision 14745)
+++ 	(revision )
@@ -1,14 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace TestPooling.Pool
-{
-    public interface IManagedPool<T> : IDisposable
-    where T: class
-    {
-      T Get();
-    }
-}
Index: anches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/ManagedPool2.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/ManagedPool2.cs	(revision 14745)
+++ 	(revision )
@@ -1,59 +1,0 @@
-﻿//using System.Collections.Generic;
-
-//namespace TestPooling.Pool {
-//  using System;
-//  using System.Collections.Concurrent;
-//  using System.IO;
-//  using System.Linq;
-//  using System.Runtime.Serialization.Formatters.Binary;
-
-//  public class ManagedPool2<T> : IDisposable where T : class {
-
-//    private static readonly ConcurrentStack<T[]> Pool = new ConcurrentStack<T[]>();
-
-//    private readonly T[] DummyPartition;
-//    public readonly int PartitionSize;
-
-//    private readonly IList<T[]> partitions = new List<T[]>();
-//    private T[] currentPartition;
-//    private int entryIndex;
-
-//    public ManagedPool2(int partitionSize, T[] dummyPartition) {
-//      PartitionSize = partitionSize;
-//      entryIndex = partitionSize;
-
-//      DummyPartition = dummyPartition;
-//    }
-
-//    public T Get() {
-//      if (entryIndex == PartitionSize) {
-//        currentPartition = GetPartition();
-//        partitions.Add(currentPartition);
-//        entryIndex = 0;
-//      }
-
-//      return currentPartition[entryIndex++];
-//    }
-
-//    private T[] GetPartition() {
-//      T[] partition;
-//      return (Pool.TryPop(out partition)) ? partition : DeepArrayCopy(DummyPartition);
-//    }
-
-//    private static T[] DeepArrayCopy(object objectToCopy) {
-//      using (var memoryStream = new MemoryStream()) {
-//        var binaryFormatter = new BinaryFormatter();
-
-//        binaryFormatter.Serialize(memoryStream, objectToCopy);
-//        memoryStream.Seek(0, SeekOrigin.Begin);
-
-//        return (T[])binaryFormatter.Deserialize(memoryStream);
-//      }
-//    }
-
-//    public void Dispose() {
-//      Pool.PushRange(partitions.ToArray());
-//      partitions.Clear();
-//    }
-//  }
-//}
Index: /branches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/ManagedPoolProvider.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/ManagedPoolProvider.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/TestPooling/Pool/ManagedPoolProvider.cs	(revision 14746)
@@ -8,14 +8,24 @@
   using System.Runtime.Serialization.Formatters.Binary;
 
+  public interface IManagedPool<T> : IDisposable where T : class {
+    T Get();
+  }
+
   public class ManagedPoolProvider<T> where T : class {
     private readonly ConcurrentStack<T[]> partitions = new ConcurrentStack<T[]>();
     private readonly ObjectPool<IManagedPool<T>> managedPools;
     private T[] DummyPartition;
+
     public readonly int PartitionSize;
+    public readonly int MaxParitionCount;
+    public const int DefaultMaxInstanceCount = 16384;
 
-    public int InstanceCount { get { return partitions.Count * PartitionSize; } }
+    public ManagedPoolProvider(int partitionSize, int maxPartitionCount = -1) {
+      PartitionSize = partitionSize;
 
-    public ManagedPoolProvider(int partitionSize) {
-      PartitionSize = partitionSize;
+      if (maxPartitionCount <= 0) {
+        MaxParitionCount = DefaultMaxInstanceCount / PartitionSize;
+      }
+
       managedPools = new ObjectPool<IManagedPool<T>>(() => new ManagedPool2<T>(this));
     }
@@ -27,4 +37,6 @@
       }
     }
+
+    public int InstanceCount { get { return partitions.Count * PartitionSize; } }
 
     public void ReleasePartitions(params T[][] partition) {
Index: /branches/PushGP/HeuristicLab.PushGP/TestPooling/Program.cs
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/TestPooling/Program.cs	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/TestPooling/Program.cs	(revision 14746)
@@ -15,5 +15,4 @@
 
     private static int TotalInstanceCount => PopulationCount * InstanceCount * ExampleCount;
-
 
     static void Main(string[] args) {
Index: /branches/PushGP/HeuristicLab.PushGP/TestPooling/TestPooling.csproj
===================================================================
--- /branches/PushGP/HeuristicLab.PushGP/TestPooling/TestPooling.csproj	(revision 14745)
+++ /branches/PushGP/HeuristicLab.PushGP/TestPooling/TestPooling.csproj	(revision 14746)
@@ -44,7 +44,5 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Pool\IManagedPool.cs" />
     <Compile Include="Pool\ManagedPool.cs" />
-    <Compile Include="Pool\ManagedPool2.cs" />
     <Compile Include="Pool\ManagedPoolProvider.cs" />
     <Compile Include="Pool\ObjectPool.cs" />
