add perf test cases to coreclr
authorShiming Ge (Pactera Technologies) <v-shige@microsoft.com>
Fri, 11 Aug 2017 08:49:42 +0000 (01:49 -0700)
committerShiming Ge (Pactera Technologies) <v-shige@microsoft.com>
Fri, 11 Aug 2017 08:49:42 +0000 (01:49 -0700)
tests/src/GC/Performance/Tests/GCMicroBench.cs [new file with mode: 0644]
tests/src/GC/Performance/Tests/LowLatency.csproj [new file with mode: 0644]
tests/src/GC/Performance/Tests/LowLatencyTest.cs [new file with mode: 0644]
tests/src/GC/Performance/Tests/MemoryPressure.cs [new file with mode: 0644]
tests/src/GC/Performance/Tests/MemoryPressure.csproj [new file with mode: 0644]
tests/src/GC/Performance/Tests/MicroBench.csproj [new file with mode: 0644]
tests/src/GC/Performance/Tests/WeakReference.csproj [new file with mode: 0644]
tests/src/GC/Performance/Tests/WeakReferenceTest.cs [new file with mode: 0644]

diff --git a/tests/src/GC/Performance/Tests/GCMicroBench.cs b/tests/src/GC/Performance/Tests/GCMicroBench.cs
new file mode 100644 (file)
index 0000000..c15daa4
--- /dev/null
@@ -0,0 +1,280 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace GC_Microbenchmarks
+{
+    // the type of objects allocated
+    // value refers to object size
+    public enum ObjectType
+    {
+        Undefined = -1,
+        Small = 8000,
+        SmallFinal = 8500, // small finalizable object
+        Large = 85000,
+        ExtraLarge = 20*1024*1024
+    }
+
+
+    // the condition to satisfy before ending the benchmark
+    public enum AllocationCondition
+    {
+        Undefined,
+        HeapSize,
+        Segments,
+        Objects
+    }
+
+
+    // the object that gets allocated
+    public class Node
+    {
+        public Node(int dataSize)
+        {
+            data = new byte[dataSize];
+        }
+
+        public byte[] data;
+    }
+
+
+    // the finalizable object that gets allocated
+    public class FNode : Node
+    {
+        public FNode(int dataSize)
+            : base(dataSize)
+        {
+        }
+
+        // puts object on finalization list
+        ~FNode()
+        {
+        }
+    }
+
+
+    public class GCMicroBench
+    {
+        // the minimum size of a segment
+        // if reserved mem increases by more than MinSegmentSize, then we can assume we've allocated a new segment
+        public const long MinSegmentSize = 4 * 1024 * 1024;
+        public const string ObjTypeParam = "/objtype:";
+        public const string ConditionParam = "/condition:";
+        public const string AmountParam = "/amount:";
+
+        // test members
+        private List<Node> m_list = new List<Node>();     // holds the allocated objects
+        private ObjectType m_objType = ObjectType.Undefined;
+        private AllocationCondition m_allocCondition = AllocationCondition.Undefined;
+        private long m_amount = 0;
+
+
+        // outputs the usage information for the app
+        public static void Usage()
+        {
+            Console.WriteLine("USAGE: /objtype: /condition: /amount:");
+            Console.WriteLine("where");
+            Console.WriteLine("\tobjtype = [small|smallfinal|large|extralarge]");
+            Console.WriteLine("\tcondition = [heapsize|segments|objects]");
+            Console.WriteLine("\tamount = the number that satisfies the condition (ex: number of objects)");
+        }
+
+        public static void Main(string[] args)
+        {
+            GCMicroBench test = new GCMicroBench();
+            if (!test.ParseArgs(args))
+            {
+                Usage();
+                return;
+            }
+            test.RunTest();
+
+        }
+
+
+        public bool ParseArgs(string[] args)
+        {
+            if (args.Length != 3)
+            {
+                return false;
+            }
+
+            for (int i = 0; i < args.Length; i++)
+            {
+                args[i] = args[i].ToLower();
+
+                if (args[i].StartsWith(ObjTypeParam))
+                {
+
+                    if (m_objType != ObjectType.Undefined)
+                    {
+                        return false;
+                    }
+
+                    switch (args[i].Substring(ObjTypeParam.Length))
+                    {
+
+                        case "small":
+                            m_objType = ObjectType.Small;
+                            break;
+                        case "smallfinal":
+                            m_objType = ObjectType.SmallFinal;
+                            break;
+                        case "large":
+                            m_objType = ObjectType.Large;
+                            break;
+                        case "extralarge":
+                            m_objType = ObjectType.ExtraLarge;
+                            break;
+                        default:
+                            return false;
+                    }
+                }
+                else if (args[i].StartsWith(ConditionParam))
+                {
+
+                    if (m_allocCondition != AllocationCondition.Undefined)
+                    {
+                        return false;
+                    }
+
+                    switch (args[i].Substring(ConditionParam.Length))
+                    {
+
+                        case "heapsize":
+                            m_allocCondition = AllocationCondition.HeapSize;
+                            break;
+                        case "segments":
+                            m_allocCondition = AllocationCondition.Segments;
+                            break;
+                        case "objects":
+                            m_allocCondition = AllocationCondition.Objects;
+                            break;
+                        default:
+                            return false;
+                    }
+                }
+                else if (args[i].StartsWith(AmountParam))
+                {
+
+                    if (m_amount != 0)
+                    {
+                        return false;
+                    }
+
+                    if ((!Int64.TryParse(args[i].Substring(AmountParam.Length), out m_amount)) || (m_amount <= 0))
+                    {
+                        Console.WriteLine("amount must be greater than 0");
+                        return false;
+                    }
+
+                    if ( (m_allocCondition == AllocationCondition.HeapSize) && ( m_amount <= GC.GetTotalMemory(false) ) )
+                    {
+                        Console.WriteLine("amount must be greater than current heap size");
+                        return false;
+                    }
+
+                }
+                else
+                {
+                    return false;
+                }
+
+            }
+
+            return true;
+        }
+
+
+        public void RunTest()
+        {
+            // allocate objType objects until heap size >= amount bytes
+            if (m_allocCondition == AllocationCondition.HeapSize)
+            {
+                while (GC.GetTotalMemory(false) <= m_amount)
+                {
+                    Allocate();
+                }
+            }
+            // allocate amount objType objects
+            else if (m_allocCondition == AllocationCondition.Objects)
+            {
+                for (long i = 0; i < m_amount; i++)
+                {
+                    Allocate();
+                }
+            }
+            // allocate objType objects until reserved VM increases by minimum segment size, amount times
+            // (this is an indirect way of determining if a new segment has been allocated)
+            else if (m_allocCondition == AllocationCondition.Segments)
+            {
+                long reservedMem;
+
+                for (long i = 0; i < m_amount; i++)
+                {
+                    reservedMem = Process.GetCurrentProcess().VirtualMemorySize64;
+
+                    do
+                    {
+                        Allocate();
+                    }
+                    while (Math.Abs(Process.GetCurrentProcess().VirtualMemorySize64 - reservedMem) < MinSegmentSize);
+                }
+            }
+
+            // allocations done
+            Deallocate();
+        }
+
+
+        public void Allocate()
+        {
+
+            Node n;
+
+            // create new finalizable object
+            if (m_objType == ObjectType.SmallFinal)
+            {
+                n = new FNode((int)m_objType);
+            }
+            else
+            {
+                n = new Node((int)m_objType);
+            }
+
+            m_list.Add(n);
+
+        }
+
+
+        // releases references to allocated objects
+        // times GC.Collect()
+        // if objects are finalizable, also times GC.WaitForPendingFinalizers()
+        public void Deallocate()
+        {
+            bool finalizable = false;
+
+            if (m_list != null)
+            {
+                finalizable  = ( (m_list.Count > 0) && (m_list[0] is FNode));
+                m_list.Clear();
+                m_list = null;
+            }
+
+            GC.Collect();
+
+            if (finalizable)
+            {
+                GC.WaitForPendingFinalizers();
+            }
+
+        }
+
+
+    }
+}
diff --git a/tests/src/GC/Performance/Tests/LowLatency.csproj b/tests/src/GC/Performance/Tests/LowLatency.csproj
new file mode 100644 (file)
index 0000000..7ea865f
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DefineConstants>$(DefineConstants);STATIC;PROJECTK_BUILD</DefineConstants>
+    <CLRTestKind>BuildOnly</CLRTestKind>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LowLatencyTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/GC/Performance/Tests/LowLatencyTest.cs b/tests/src/GC/Performance/Tests/LowLatencyTest.cs
new file mode 100644 (file)
index 0000000..8f40104
--- /dev/null
@@ -0,0 +1,185 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Xml;
+using System.Runtime;
+
+namespace GCTest
+{
+
+    public class GCTestC
+    {
+
+        static int loid=0; // to give a "unique" identifier
+
+        public static void Usage()
+        {
+            Console.WriteLine("Usage");
+            Console.WriteLine("LowLatency.exe <iterations> <lowlatency|interactive|batch>");
+        }
+
+
+        static void Main(string[] args)
+        {
+            if (args.Length!=2)
+            {
+                Usage();
+                return;
+            }
+
+            int iters = 0;
+            if (!Int32.TryParse(args[0], out iters))
+            {
+                Usage();
+                return;
+            }
+
+            GCLatencyMode gcMode;
+
+            switch (args[1].ToLower())
+            {
+                case "lowlatency":
+                    gcMode = GCLatencyMode.LowLatency;
+                    break;
+                case "interactive":
+                    gcMode = GCLatencyMode.Interactive;
+                    break;
+                case "batch":
+                    gcMode = GCLatencyMode.Batch;
+                    break;
+                default:
+                    Usage();
+                    return;
+            }
+
+            GCTestC test = new GCTestC();
+            test.DoTest(iters, gcMode);
+        }
+
+
+        private void LoadData( int count, ref long[] values )
+        {
+
+            loid++;
+            Hashtable aMap = new Hashtable(count);
+            byte[] aBuffer = null;
+
+            using (StreamReader reader = new StreamReader("clunie_small.xml"))
+            {
+                aBuffer = new byte[reader.BaseStream.Length];
+                reader.BaseStream.Read(aBuffer, 0, (int)reader.BaseStream.Length);
+            }
+
+            using (MemoryStream aMemStream = new MemoryStream(aBuffer))
+            {
+                aBuffer = null;
+
+                values[0] = PerformanceCounter.QueryCounter;
+                for (int i = 0; i < count; i++)
+                {
+                    Thread.Sleep(0); // simulate waiting on arrival of new data...
+
+                    // create XmlDocuments
+                    XmlDocument aXmlDoc = new XmlDocument();
+                    aXmlDoc.Load(aMemStream);
+                    aMap.Add("1.2.3" + loid.ToString() + i.ToString(), aXmlDoc);
+                    aXmlDoc = null;
+
+                    // reset the position in the memory stream to the beginning
+                    aMemStream.Seek(0, SeekOrigin.Begin);
+
+                    values[i + 1] = PerformanceCounter.QueryCounter;
+                }
+
+            }
+
+        }
+
+
+        private void PrintStat(long[] values)
+        {
+            int count=values.Length-1;
+            long max = values[1]-values[0];
+
+            for (int i=0;i<count;i++)
+            {
+                max = Math.Max(max, (values[i+1]-values[i]));
+            }
+
+            //Console.WriteLine("Maximum of {0}: {1}", count, PerformanceCounter.PrintTime(PerformanceCounter.Seconds(max)));
+
+        }
+
+
+        public void DoTest(int count, GCLatencyMode gcMode)
+        {
+
+            GCLatencyMode oldMode = GCSettings.LatencyMode;
+
+            long[] values = new long[count+1]; // reuse this array for every test ...
+
+            RuntimeHelpers.PrepareConstrainedRegions();
+            try
+            {
+                // Load Data
+                GCSettings.LatencyMode = gcMode;
+                LoadData(count, ref values);
+            }
+            finally
+            {
+                GCSettings.LatencyMode = oldMode;
+            }
+
+            PrintStat(values);
+        }
+
+
+        public static class PerformanceCounter
+        {
+            [DllImport("kernel32.dll", CallingConvention=CallingConvention.Winapi, EntryPoint="QueryPerformanceFrequency")]
+            private static extern int QueryPerformanceFrequency_int(ref long count);
+            [DllImport("kernel32.dll", CallingConvention=CallingConvention.Winapi, EntryPoint="QueryPerformanceCounter")]
+            private static extern int QueryPerformanceCounter_int(ref long count);
+
+            public static long QueryCounter
+            {
+                get
+                {
+                    long var = 0;
+                    QueryPerformanceCounter_int(ref var);
+                    return var;
+                }
+            }
+
+            public static long Frequency
+            {
+                get
+                {
+                    long var = 0;
+                    QueryPerformanceFrequency_int(ref var);
+                    return var;
+                }
+            }
+
+            public static double Seconds(long v)
+            {
+                return (double)v/Frequency;
+            }
+
+
+            public static string PrintTime(double time)
+            {
+                return (time*1000).ToString("0.000ms");
+            }
+        }
+
+    }
+}
diff --git a/tests/src/GC/Performance/Tests/MemoryPressure.cs b/tests/src/GC/Performance/Tests/MemoryPressure.cs
new file mode 100644 (file)
index 0000000..333723f
--- /dev/null
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+public class MemoryPressure
+{
+       private long iterations = 0;
+
+       public static void Usage()
+       {
+               Console.WriteLine("Usage");
+               Console.WriteLine("MemoryPressure.exe <iterations> <add|remove>");
+       }
+
+       public static void Main(string[] args)                                                                           
+       {
+               if (args.Length!=2)
+               {
+                       Usage();
+                       return;
+               }
+               long iterations = 0;
+               if (!long.TryParse(args[0], out iterations))
+               {
+                       Usage();
+                       return;
+               }
+
+               if(iterations == 0)
+               {
+                       iterations=200;
+               }
+
+               MemoryPressure mp = new MemoryPressure(iterations);
+
+               switch (args[1].ToLower())
+               {
+                       case "add":
+                               mp.AddMemoryPressure();
+                               break;
+                       case "remove":
+                               mp.RemoveMemoryPressure();
+                               break;
+                       default:
+                               Usage();
+                               return;
+               }
+       }
+
+       public MemoryPressure(long iters)
+       {
+               iterations = iters;
+       }
+
+       public void RemoveMemoryPressure()
+       {
+               for(long i = 0; i < iterations; i++)
+               {
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+               }
+
+               for(long i = 0; i < iterations; i++)
+               {
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+                       GC.RemoveMemoryPressure(Int32.MaxValue);
+               }
+       }
+
+       public void AddMemoryPressure()
+       {
+
+               GC.AddMemoryPressure(Int32.MaxValue);
+
+               for(long i = 0; i < iterations; i++)
+               {
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+                       GC.AddMemoryPressure(Int32.MaxValue);
+               }
+       }
+}
diff --git a/tests/src/GC/Performance/Tests/MemoryPressure.csproj b/tests/src/GC/Performance/Tests/MemoryPressure.csproj
new file mode 100644 (file)
index 0000000..ab80573
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DefineConstants>$(DefineConstants);STATIC;PROJECTK_BUILD</DefineConstants>
+    <CLRTestKind>BuildOnly</CLRTestKind>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="MemoryPressure.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/GC/Performance/Tests/MicroBench.csproj b/tests/src/GC/Performance/Tests/MicroBench.csproj
new file mode 100644 (file)
index 0000000..e14647c
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DefineConstants>$(DefineConstants);STATIC;PROJECTK_BUILD</DefineConstants>
+    <CLRTestKind>BuildOnly</CLRTestKind>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GCMicroBench.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/GC/Performance/Tests/WeakReference.csproj b/tests/src/GC/Performance/Tests/WeakReference.csproj
new file mode 100644 (file)
index 0000000..90c73d9
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DefineConstants>$(DefineConstants);STATIC;PROJECTK_BUILD</DefineConstants>
+    <CLRTestKind>BuildOnly</CLRTestKind>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="WeakReferenceTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/GC/Performance/Tests/WeakReferenceTest.cs b/tests/src/GC/Performance/Tests/WeakReferenceTest.cs
new file mode 100644 (file)
index 0000000..4c98e2c
--- /dev/null
@@ -0,0 +1,384 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+class WeakReferenceTest
+{
+    // test variables
+    private Object[] m_objectArray;
+    private WeakReference[] m_wrArray;
+    private const int m_numWRs = 50;
+    private long m_numIters;
+    private bool m_alive = true;
+    
+    public static void Usage()
+    {
+        Console.WriteLine("USAGE: WeakReference.exe <num iterations> <alive|dead> <gettarget|settarget|isalive|alloc|alloctrack>");
+    }
+
+    static void Main(string[] args)
+    {
+        if (args.Length!=3)
+               {
+                       Usage();
+                       return;
+               }
+        
+        long iterations = 0;
+        if (!long.TryParse(args[0], out iterations))
+               {
+                       Usage();
+                       return;
+               }
+
+        bool alive = true;
+        if (args[1].ToLower()=="dead")
+        {
+            alive = false;
+            Console.WriteLine("Using dead targets");
+        }
+
+        WeakReferenceTest test = new WeakReferenceTest(iterations, alive);
+        test.Init(); 
+
+        switch (args[2].ToLower())
+        {
+            case "gettarget":
+                test.GetTargetTest();
+                break;
+            case "settarget":
+                test.SetTargetTest();
+                break;
+            case "isalive":
+                test.IsAliveTest();
+                break;
+            case "alloc":
+                test.AllocTest(false);
+                break;
+            case "alloctrack":
+                test.AllocTest(true);
+                break;
+            default:
+                Usage();
+                break;
+        }
+         
+    }
+    
+    
+    public WeakReferenceTest(long numIters, bool alive)
+    {
+        m_numIters = numIters;
+        m_alive = alive;
+        
+        m_objectArray = new Object[m_numWRs];
+        m_wrArray = new WeakReference[m_numWRs];
+        
+        for (int i = 0; i < m_numWRs; ++i)
+        {
+            if (m_alive)
+            {
+                // create a new string object
+                String s = "blah" + i;
+                m_objectArray[i] = s;
+            }
+            else
+            {
+                // set to null
+                m_objectArray[i] = null;
+            }
+            
+        }
+      
+        //GC now to get that out of the way
+        GC.Collect();          
+    }
+    
+    
+    public void Init()
+    {
+
+        for (int i = 0; i < m_numWRs; ++i)
+        {            
+            m_wrArray[i] = new WeakReference(m_objectArray[i]);
+        }    
+        GC.Collect();    
+
+    }
+
+    public void AllocTest(bool trackResurrection)
+    {
+                    
+        for (long i = 0; i < m_numIters; i++)
+        {                           
+            m_wrArray[0] = new WeakReference(m_objectArray[0], trackResurrection);
+            m_wrArray[1] = new WeakReference(m_objectArray[1], trackResurrection);
+            m_wrArray[2] = new WeakReference(m_objectArray[2], trackResurrection);
+            m_wrArray[3] = new WeakReference(m_objectArray[3], trackResurrection);
+            m_wrArray[4] = new WeakReference(m_objectArray[4], trackResurrection);
+            m_wrArray[5] = new WeakReference(m_objectArray[5], trackResurrection);
+            m_wrArray[6] = new WeakReference(m_objectArray[6], trackResurrection);
+            m_wrArray[7] = new WeakReference(m_objectArray[7], trackResurrection);
+            m_wrArray[8] = new WeakReference(m_objectArray[8], trackResurrection);
+            m_wrArray[9] = new WeakReference(m_objectArray[9], trackResurrection);
+
+            m_wrArray[10] = new WeakReference(m_objectArray[10], trackResurrection);
+            m_wrArray[11] = new WeakReference(m_objectArray[11], trackResurrection);
+            m_wrArray[12] = new WeakReference(m_objectArray[12], trackResurrection);
+            m_wrArray[13] = new WeakReference(m_objectArray[13], trackResurrection);
+            m_wrArray[14] = new WeakReference(m_objectArray[14], trackResurrection);
+            m_wrArray[15] = new WeakReference(m_objectArray[15], trackResurrection);
+            m_wrArray[16] = new WeakReference(m_objectArray[16], trackResurrection);
+            m_wrArray[17] = new WeakReference(m_objectArray[17], trackResurrection);
+            m_wrArray[18] = new WeakReference(m_objectArray[18], trackResurrection);
+            m_wrArray[19] = new WeakReference(m_objectArray[19], trackResurrection);
+
+            m_wrArray[20] = new WeakReference(m_objectArray[20], trackResurrection);
+            m_wrArray[21] = new WeakReference(m_objectArray[21], trackResurrection);
+            m_wrArray[22] = new WeakReference(m_objectArray[22], trackResurrection);
+            m_wrArray[23] = new WeakReference(m_objectArray[23], trackResurrection);
+            m_wrArray[24] = new WeakReference(m_objectArray[24], trackResurrection);
+            m_wrArray[25] = new WeakReference(m_objectArray[25], trackResurrection);
+            m_wrArray[26] = new WeakReference(m_objectArray[26], trackResurrection);
+            m_wrArray[27] = new WeakReference(m_objectArray[27], trackResurrection);
+            m_wrArray[28] = new WeakReference(m_objectArray[28], trackResurrection);
+            m_wrArray[29] = new WeakReference(m_objectArray[29], trackResurrection);
+
+            m_wrArray[30] = new WeakReference(m_objectArray[30], trackResurrection);
+            m_wrArray[31] = new WeakReference(m_objectArray[31], trackResurrection);
+            m_wrArray[32] = new WeakReference(m_objectArray[32], trackResurrection);
+            m_wrArray[33] = new WeakReference(m_objectArray[33], trackResurrection);
+            m_wrArray[34] = new WeakReference(m_objectArray[34], trackResurrection);
+            m_wrArray[35] = new WeakReference(m_objectArray[35], trackResurrection);
+            m_wrArray[36] = new WeakReference(m_objectArray[36], trackResurrection);
+            m_wrArray[37] = new WeakReference(m_objectArray[37], trackResurrection);
+            m_wrArray[38] = new WeakReference(m_objectArray[38], trackResurrection);
+            m_wrArray[39] = new WeakReference(m_objectArray[39], trackResurrection);
+
+            m_wrArray[40] = new WeakReference(m_objectArray[40], trackResurrection);
+            m_wrArray[41] = new WeakReference(m_objectArray[41], trackResurrection);
+            m_wrArray[42] = new WeakReference(m_objectArray[42], trackResurrection);
+            m_wrArray[43] = new WeakReference(m_objectArray[43], trackResurrection);
+            m_wrArray[44] = new WeakReference(m_objectArray[44], trackResurrection);
+            m_wrArray[45] = new WeakReference(m_objectArray[45], trackResurrection);
+            m_wrArray[46] = new WeakReference(m_objectArray[46], trackResurrection);
+            m_wrArray[47] = new WeakReference(m_objectArray[47], trackResurrection);
+            m_wrArray[48] = new WeakReference(m_objectArray[48], trackResurrection);
+            m_wrArray[49] = new WeakReference(m_objectArray[49], trackResurrection);
+             
+            for (int j=0; j< m_wrArray.Length; j++)
+            {
+                m_wrArray[j] = null;
+            }
+            
+            GC.Collect();
+    
+        }
+        
+    }
+
+       
+       
+    public void SetTargetTest()
+    {
+        Init();
+        
+        for (long i = 0; i < m_numIters; i++)
+        {                           
+            m_wrArray[0].Target = m_objectArray[0];
+            m_wrArray[1].Target = m_objectArray[1];
+            m_wrArray[2].Target = m_objectArray[2];
+            m_wrArray[3].Target = m_objectArray[3];
+            m_wrArray[4].Target = m_objectArray[4];
+            m_wrArray[5].Target = m_objectArray[5];
+            m_wrArray[6].Target = m_objectArray[6];
+            m_wrArray[7].Target = m_objectArray[7];
+            m_wrArray[8].Target = m_objectArray[8];
+            m_wrArray[9].Target = m_objectArray[9];
+
+            m_wrArray[10].Target = m_objectArray[10];
+            m_wrArray[11].Target = m_objectArray[11];
+            m_wrArray[12].Target = m_objectArray[12];
+            m_wrArray[13].Target = m_objectArray[13];
+            m_wrArray[14].Target = m_objectArray[14];
+            m_wrArray[15].Target = m_objectArray[15];
+            m_wrArray[16].Target = m_objectArray[16];
+            m_wrArray[17].Target = m_objectArray[17];
+            m_wrArray[18].Target = m_objectArray[18];
+            m_wrArray[19].Target = m_objectArray[19];
+
+            m_wrArray[20].Target = m_objectArray[20];
+            m_wrArray[21].Target = m_objectArray[21];
+            m_wrArray[22].Target = m_objectArray[22];
+            m_wrArray[23].Target = m_objectArray[23];
+            m_wrArray[24].Target = m_objectArray[24];
+            m_wrArray[25].Target = m_objectArray[25];
+            m_wrArray[26].Target = m_objectArray[26];
+            m_wrArray[27].Target = m_objectArray[27];
+            m_wrArray[28].Target = m_objectArray[28];
+            m_wrArray[29].Target = m_objectArray[29];
+
+            m_wrArray[30].Target = m_objectArray[30];
+            m_wrArray[31].Target = m_objectArray[31];
+            m_wrArray[32].Target = m_objectArray[32];
+            m_wrArray[33].Target = m_objectArray[33];
+            m_wrArray[34].Target = m_objectArray[34];
+            m_wrArray[35].Target = m_objectArray[35];
+            m_wrArray[36].Target = m_objectArray[36];
+            m_wrArray[37].Target = m_objectArray[37];
+            m_wrArray[38].Target = m_objectArray[38];
+            m_wrArray[39].Target = m_objectArray[39];
+
+            m_wrArray[40].Target = m_objectArray[40];
+            m_wrArray[41].Target = m_objectArray[41];
+            m_wrArray[42].Target = m_objectArray[42];
+            m_wrArray[43].Target = m_objectArray[43];
+            m_wrArray[44].Target = m_objectArray[44];
+            m_wrArray[45].Target = m_objectArray[45];
+            m_wrArray[46].Target = m_objectArray[46];
+            m_wrArray[47].Target = m_objectArray[47];
+            m_wrArray[48].Target = m_objectArray[48];
+            m_wrArray[49].Target = m_objectArray[49];
+             
+        }
+
+    }
+    
+    public void GetTargetTest()
+    {
+    
+        Init();
+        Object o = null;
+                
+        for (long i = 0; i < m_numIters; i++)
+        {                             
+            o = m_wrArray[0].Target;
+            o = m_wrArray[1].Target;
+            o = m_wrArray[2].Target;
+            o = m_wrArray[3].Target;
+            o = m_wrArray[4].Target;
+            o = m_wrArray[5].Target;
+            o = m_wrArray[6].Target;
+            o = m_wrArray[7].Target;
+            o = m_wrArray[8].Target;
+            o = m_wrArray[9].Target;
+
+            o = m_wrArray[10].Target;
+            o = m_wrArray[11].Target;
+            o = m_wrArray[12].Target;
+            o = m_wrArray[13].Target;
+            o = m_wrArray[14].Target;
+            o = m_wrArray[15].Target;
+            o = m_wrArray[16].Target;
+            o = m_wrArray[17].Target;
+            o = m_wrArray[18].Target;
+            o = m_wrArray[19].Target;
+
+            o = m_wrArray[20].Target;
+            o = m_wrArray[21].Target;
+            o = m_wrArray[22].Target;
+            o = m_wrArray[23].Target;
+            o = m_wrArray[24].Target;
+            o = m_wrArray[25].Target;
+            o = m_wrArray[26].Target;
+            o = m_wrArray[27].Target;
+            o = m_wrArray[28].Target;
+            o = m_wrArray[29].Target;
+
+            o = m_wrArray[30].Target;
+            o = m_wrArray[31].Target;
+            o = m_wrArray[32].Target;
+            o = m_wrArray[33].Target;
+            o = m_wrArray[34].Target;
+            o = m_wrArray[35].Target;
+            o = m_wrArray[36].Target;
+            o = m_wrArray[37].Target;
+            o = m_wrArray[38].Target;
+            o = m_wrArray[39].Target;
+
+            o = m_wrArray[40].Target;
+            o = m_wrArray[41].Target;
+            o = m_wrArray[42].Target;
+            o = m_wrArray[43].Target;
+            o = m_wrArray[44].Target;
+            o = m_wrArray[45].Target;
+            o = m_wrArray[46].Target;
+            o = m_wrArray[47].Target;
+            o = m_wrArray[48].Target;
+            o = m_wrArray[49].Target;
+              
+        }
+
+    }
+    
+    
+    public void IsAliveTest()
+    {
+        bool b = false;        
+        Init();
+                
+        for (int i = 0; i < m_numIters; i++)
+        {              
+
+            b = m_wrArray[0].IsAlive;
+            b = m_wrArray[1].IsAlive;
+            b = m_wrArray[2].IsAlive;
+            b = m_wrArray[3].IsAlive;
+            b = m_wrArray[4].IsAlive;
+            b = m_wrArray[5].IsAlive;
+            b = m_wrArray[6].IsAlive;
+            b = m_wrArray[7].IsAlive;
+            b = m_wrArray[8].IsAlive;
+            b = m_wrArray[9].IsAlive;
+
+            b = m_wrArray[10].IsAlive;
+            b = m_wrArray[11].IsAlive;
+            b = m_wrArray[12].IsAlive;
+            b = m_wrArray[13].IsAlive;
+            b = m_wrArray[14].IsAlive;
+            b = m_wrArray[15].IsAlive;
+            b = m_wrArray[16].IsAlive;
+            b = m_wrArray[17].IsAlive;
+            b = m_wrArray[18].IsAlive;
+            b = m_wrArray[19].IsAlive;
+
+            b = m_wrArray[20].IsAlive;
+            b = m_wrArray[21].IsAlive;
+            b = m_wrArray[22].IsAlive;
+            b = m_wrArray[23].IsAlive;
+            b = m_wrArray[24].IsAlive;
+            b = m_wrArray[25].IsAlive;
+            b = m_wrArray[26].IsAlive;
+            b = m_wrArray[27].IsAlive;
+            b = m_wrArray[28].IsAlive;
+            b = m_wrArray[29].IsAlive;
+
+            b = m_wrArray[30].IsAlive;
+            b = m_wrArray[31].IsAlive;
+            b = m_wrArray[32].IsAlive;
+            b = m_wrArray[33].IsAlive;
+            b = m_wrArray[34].IsAlive;
+            b = m_wrArray[35].IsAlive;
+            b = m_wrArray[36].IsAlive;
+            b = m_wrArray[37].IsAlive;
+            b = m_wrArray[38].IsAlive;
+            b = m_wrArray[39].IsAlive;
+
+            b = m_wrArray[40].IsAlive;
+            b = m_wrArray[41].IsAlive;
+            b = m_wrArray[42].IsAlive;
+            b = m_wrArray[43].IsAlive;
+            b = m_wrArray[44].IsAlive;
+            b = m_wrArray[45].IsAlive;
+            b = m_wrArray[46].IsAlive;
+            b = m_wrArray[47].IsAlive;
+            b = m_wrArray[48].IsAlive;
+            b = m_wrArray[49].IsAlive;
+            
+        }
+
+    }    
+
+}