diff --git a/Perspex.sln b/Perspex.sln
index f7d69d4db1..bc7e0560af 100644
--- a/Perspex.sln
+++ b/Perspex.sln
@@ -140,6 +140,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog", "samples\C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.UnitTests", "tests\Perspex.UnitTests\Perspex.UnitTests.csproj", "{88060192-33D5-4932-B0F9-8BD2763E857D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Benchmarks", "tests\Perspex.Benchmarks\Perspex.Benchmarks.csproj", "{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{fb05ac90-89ba-4f2f-a924-f37875fb547c}*SharedItemsImports = 4
@@ -1295,6 +1297,30 @@ Global
{88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhone.Build.0 = Release|Any CPU
{88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhone.Build.0 = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1339,5 +1365,6 @@ Global
{E1AA3DBF-9056-4530-9376-18119A7A3FFE} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{61BEC86C-F307-4295-B5B8-9428610D7D55} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{88060192-33D5-4932-B0F9-8BD2763E857D} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
EndGlobal
diff --git a/tests/Perspex.Benchmarks/App.config b/tests/Perspex.Benchmarks/App.config
new file mode 100644
index 0000000000..121e469348
--- /dev/null
+++ b/tests/Perspex.Benchmarks/App.config
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Perspex.Benchmarks/Controls/Initialization.cs b/tests/Perspex.Benchmarks/Controls/Initialization.cs
new file mode 100644
index 0000000000..2ce4ad9b43
--- /dev/null
+++ b/tests/Perspex.Benchmarks/Controls/Initialization.cs
@@ -0,0 +1,35 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Linq;
+using BenchmarkDotNet.Attributes;
+using Perspex.Controls;
+using Perspex.Layout;
+using Perspex.UnitTests;
+using Perspex.VisualTree;
+
+namespace Perspex.Benchmarks.Controls
+{
+ public class Initialization
+ {
+ [Benchmark]
+ public void Add_And_Style_TextBox()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var window = new Window
+ {
+ Content = new TextBox(),
+ };
+
+ LayoutManager.Instance.ExecuteInitialLayoutPass(window);
+
+ if (((TextBox)window.Content).GetVisualChildren().Count() != 1)
+ {
+ throw new Exception("Control not styled.");
+ }
+ }
+ }
+ }
+}
diff --git a/tests/Perspex.Benchmarks/Perspex.Benchmarks.csproj b/tests/Perspex.Benchmarks/Perspex.Benchmarks.csproj
new file mode 100644
index 0000000000..909bc8de82
--- /dev/null
+++ b/tests/Perspex.Benchmarks/Perspex.Benchmarks.csproj
@@ -0,0 +1,130 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}
+ Exe
+ Properties
+ Perspex.Benchmarks
+ Perspex.Benchmarks
+ v4.5
+ 512
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\packages\BenchmarkDotNet.0.9.2\lib\net45\BenchmarkDotNet.dll
+ True
+
+
+
+
+
+ ..\..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll
+ True
+
+
+ ..\..\packages\AutoFixture.3.40.0\lib\net40\Ploeh.AutoFixture.dll
+ True
+
+
+ ..\..\packages\AutoFixture.AutoMoq.3.40.0\lib\net40\Ploeh.AutoFixture.AutoMoq.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+ Perspex.Animation
+
+
+ {799a7bb5-3c2c-48b6-85a7-406a12c420da}
+ Perspex.Application
+
+
+ {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ Perspex.Base
+
+
+ {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ Perspex.Controls
+
+
+ {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ Perspex.Input
+
+
+ {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ Perspex.Interactivity
+
+
+ {42472427-4774-4c81-8aff-9f27b8e31721}
+ Perspex.Layout
+
+
+ {eb582467-6abb-43a1-b052-e981ba910e3a}
+ Perspex.SceneGraph
+
+
+ {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ Perspex.Styling
+
+
+ {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
+ Perspex.Themes.Default
+
+
+ {88060192-33d5-4932-b0f9-8bd2763e857d}
+ Perspex.UnitTests
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Perspex.Benchmarks/Program.cs b/tests/Perspex.Benchmarks/Program.cs
new file mode 100644
index 0000000000..04575f8ed0
--- /dev/null
+++ b/tests/Perspex.Benchmarks/Program.cs
@@ -0,0 +1,29 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Linq;
+using System.Reflection;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+using Perspex.Benchmarks.Controls;
+
+namespace Perspex.Benchmarks
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Use reflection for a more maintainable way of creating the benchmark switcher,
+ // Benchmarks are listed in namespace order first (e.g. BenchmarkDotNet.Samples.CPU,
+ // BenchmarkDotNet.Samples.IL, etc) then by name, so the output is easy to understand
+ var benchmarks = Assembly.GetExecutingAssembly().GetTypes()
+ .Where(t => t.GetMethods(BindingFlags.Instance | BindingFlags.Public)
+ .Any(m => m.GetCustomAttributes(typeof(BenchmarkAttribute), false).Any()))
+ .OrderBy(t => t.Namespace)
+ .ThenBy(t => t.Name)
+ .ToArray();
+ var benchmarkSwitcher = new BenchmarkSwitcher(benchmarks);
+ benchmarkSwitcher.Run(args);
+ }
+ }
+}
diff --git a/tests/Perspex.Benchmarks/Properties/AssemblyInfo.cs b/tests/Perspex.Benchmarks/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..e8b6d6d82c
--- /dev/null
+++ b/tests/Perspex.Benchmarks/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Perspex.Benchmarks")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Perspex.Benchmarks")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("410ac439-81a1-4eb5-b5e9-6a7fc6b77f4b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tests/Perspex.Benchmarks/packages.config b/tests/Perspex.Benchmarks/packages.config
new file mode 100644
index 0000000000..b1d27d4562
--- /dev/null
+++ b/tests/Perspex.Benchmarks/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file