summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShiming Ge <v-shige@microsoft.com>2017-08-15 10:15:22 +0800
committerGitHub <noreply@github.com>2017-08-15 10:15:22 +0800
commit82b82b4e88350708e8dd139255c0ee648f9b3fbd (patch)
tree1d261c0885f2aee2d366d44fc430c475f0c3afde
parentb6fa02e6ede80a5aa2a07de141e34cc45386ada1 (diff)
parentbf0e1fff5f1ed9ceafa64bdb8192abab36c2f641 (diff)
downloadcoreclr-82b82b4e88350708e8dd139255c0ee648f9b3fbd.tar.gz
coreclr-82b82b4e88350708e8dd139255c0ee648f9b3fbd.tar.bz2
coreclr-82b82b4e88350708e8dd139255c0ee648f9b3fbd.zip
Merge pull request #13334 from shimingsg/v-shige/add-perftc-0811
add perf test cases(MicroBench, MemoryPressure, etc) to coreclr
-rw-r--r--tests/src/GC/Performance/Tests/GCMicroBench.cs280
-rw-r--r--tests/src/GC/Performance/Tests/LowLatency.csproj35
-rw-r--r--tests/src/GC/Performance/Tests/LowLatencyTest.cs125
-rw-r--r--tests/src/GC/Performance/Tests/MemoryPressure.cs107
-rw-r--r--tests/src/GC/Performance/Tests/MemoryPressure.csproj35
-rw-r--r--tests/src/GC/Performance/Tests/MicroBench.csproj35
-rw-r--r--tests/src/GC/Performance/Tests/WeakReference.csproj35
-rw-r--r--tests/src/GC/Performance/Tests/WeakReferenceTest.cs384
8 files changed, 1036 insertions, 0 deletions
diff --git a/tests/src/GC/Performance/Tests/GCMicroBench.cs b/tests/src/GC/Performance/Tests/GCMicroBench.cs
new file mode 100644
index 0000000000..c15daa47c3
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/GCMicroBench.cs
@@ -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
index 0000000000..7ea865f9e4
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/LowLatency.csproj
@@ -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
index 0000000000..db4cc4c440
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/LowLatencyTest.cs
@@ -0,0 +1,125 @@
+// 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;
+using System.Diagnostics;
+
+namespace GCTest
+{
+ public class GCTestC
+ {
+ private static int loid = 0; // to give a "unique" identifier
+ private static Stopwatch s_stopWatch = new Stopwatch();
+ 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)
+ {
+ loid++;
+ Hashtable aMap = new Hashtable(count);
+ byte[] aBuffer = null;
+ long maxElapsed = 0;
+ 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;
+ s_stopWatch.Restart();
+ 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);
+ s_stopWatch.Stop();
+ if (maxElapsed < s_stopWatch.ElapsedMilliseconds)
+ {
+ maxElapsed = s_stopWatch.ElapsedMilliseconds;
+ }
+ }
+
+ Console.WriteLine("Maximum of {0}: {1}", count, maxElapsed);
+ }
+
+ }
+
+ public void DoTest(int count, GCLatencyMode gcMode)
+ {
+ GCLatencyMode oldMode = GCSettings.LatencyMode;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ // Load Data
+ GCSettings.LatencyMode = gcMode;
+ LoadData(count);
+ }
+ finally
+ {
+ GCSettings.LatencyMode = oldMode;
+ }
+ }
+
+ }
+}
diff --git a/tests/src/GC/Performance/Tests/MemoryPressure.cs b/tests/src/GC/Performance/Tests/MemoryPressure.cs
new file mode 100644
index 0000000000..333723fa53
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/MemoryPressure.cs
@@ -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
index 0000000000..ab80573fc5
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/MemoryPressure.csproj
@@ -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
index 0000000000..e14647c0c7
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/MicroBench.csproj
@@ -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
index 0000000000..90c73d9c63
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/WeakReference.csproj
@@ -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
index 0000000000..4c98e2ca30
--- /dev/null
+++ b/tests/src/GC/Performance/Tests/WeakReferenceTest.cs
@@ -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;
+
+ }
+
+ }
+
+}