From 868acf269a86d08199cac16a41d503208e5f5f1d Mon Sep 17 00:00:00 2001 From: Boring3 Date: Mon, 9 Nov 2020 00:44:14 +0800 Subject: [PATCH] first commit --- .gitignore | 362 +++++++++++++++++++++++++++ .vscode/tasks.json | 51 ++++ Benchmark/Benchmark.csproj | 16 ++ Benchmark/FastNewBenchmark.cs | 36 +++ Benchmark/Program.cs | 13 + FastGenericNew.sln | 31 +++ FastGenericNew/ConstructorOf.cs | 128 ++++++++++ FastGenericNew/FastGenericNew.csproj | 15 ++ FastGenericNew/FastNew.cs | 177 +++++++++++++ LICENSE | 21 ++ README.md | 47 ++++ meaninglessLogo.png | Bin 0 -> 24647 bytes 12 files changed, 897 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/tasks.json create mode 100644 Benchmark/Benchmark.csproj create mode 100644 Benchmark/FastNewBenchmark.cs create mode 100644 Benchmark/Program.cs create mode 100644 FastGenericNew.sln create mode 100644 FastGenericNew/ConstructorOf.cs create mode 100644 FastGenericNew/FastGenericNew.csproj create mode 100644 FastGenericNew/FastNew.cs create mode 100644 LICENSE create mode 100644 README.md create mode 100644 meaninglessLogo.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a8542d --- /dev/null +++ b/.gitignore @@ -0,0 +1,362 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..9b8d58c --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,51 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "debug-build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/FastGenericNew/FastGenericNew.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary", + "-c", + "Debug" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, + { + "label": "release-build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/FastGenericNew/FastGenericNew.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary", + "-c", + "Release" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, + { + "label": "Run Benchmark", + "command": "dotnet", + "type": "process", + "args": [ + "run", + "--project", + "${workspaceFolder}/Benchmark/Benchmark.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary", + "-c", + "Release" + ], + "group": "build", + "problemMatcher": "$msCompile" + } + ] +} diff --git a/Benchmark/Benchmark.csproj b/Benchmark/Benchmark.csproj new file mode 100644 index 0000000..b847436 --- /dev/null +++ b/Benchmark/Benchmark.csproj @@ -0,0 +1,16 @@ + + + Exe + net5.0 + + + + + + + + + + + + diff --git a/Benchmark/FastNewBenchmark.cs b/Benchmark/FastNewBenchmark.cs new file mode 100644 index 0000000..95d6540 --- /dev/null +++ b/Benchmark/FastNewBenchmark.cs @@ -0,0 +1,36 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Order; +using FastGenericNew; +#pragma warning disable CA1822 // Member does not access instance data and can be marked as static + +namespace Benchmark +{ + [StopOnFirstError] + [MemoryDiagnoser] + [DisassemblyDiagnoser] + [BaselineColumn] + [Orderer(SummaryOrderPolicy.FastestToSlowest)] + public class FastNewBenchmark + { + [Benchmark] + public Example DirectNew() => + new Example(); + + [Benchmark(Baseline = true)] + public Example FastNewT() => + Test.FastNew(); + + [Benchmark] + public Example NewT() => + Test.New(); + } + + public static class Test where T : new() + { + public static T FastNew() => FastNew.CreateInstance(); + + public static T New() => new T(); + } + + public class Example { } +} \ No newline at end of file diff --git a/Benchmark/Program.cs b/Benchmark/Program.cs new file mode 100644 index 0000000..1a0df29 --- /dev/null +++ b/Benchmark/Program.cs @@ -0,0 +1,13 @@ +using BenchmarkDotNet.Running; + +namespace Benchmark +{ + class Program + { + static void Main() + { + BenchmarkRunner.Run(); + + } + } +} \ No newline at end of file diff --git a/FastGenericNew.sln b/FastGenericNew.sln new file mode 100644 index 0000000..5a467f8 --- /dev/null +++ b/FastGenericNew.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30626.31 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGenericNew", "FastGenericNew\FastGenericNew.csproj", "{42CB2629-2845-4EA9-A920-D5E27F34166C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "Benchmark\Benchmark.csproj", "{2E299ABC-67E9-4163-A111-65557046380E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {42CB2629-2845-4EA9-A920-D5E27F34166C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42CB2629-2845-4EA9-A920-D5E27F34166C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42CB2629-2845-4EA9-A920-D5E27F34166C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42CB2629-2845-4EA9-A920-D5E27F34166C}.Release|Any CPU.Build.0 = Release|Any CPU + {2E299ABC-67E9-4163-A111-65557046380E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E299ABC-67E9-4163-A111-65557046380E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E299ABC-67E9-4163-A111-65557046380E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E299ABC-67E9-4163-A111-65557046380E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {75D760F6-62AB-467E-AA84-5208960EE4F5} + EndGlobalSection +EndGlobal diff --git a/FastGenericNew/ConstructorOf.cs b/FastGenericNew/ConstructorOf.cs new file mode 100644 index 0000000..f136c23 --- /dev/null +++ b/FastGenericNew/ConstructorOf.cs @@ -0,0 +1,128 @@ +using System; +using System.Reflection; + +namespace FastGenericNew +{ + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter) + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2) + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + typeof(TParameter3), + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + typeof(TParameter4), + typeof(TParameter5), + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + typeof(TParameter4), + typeof(TParameter5), + typeof(TParameter6), + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + typeof(TParameter4), + typeof(TParameter5), + typeof(TParameter6), + typeof(TParameter7), + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + typeof(TParameter4), + typeof(TParameter5), + typeof(TParameter6), + typeof(TParameter7), + typeof(TParameter8), + }, null); + } + + public static class ConstructorOf + { + public static readonly ConstructorInfo value = + typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] + { + typeof(TParameter), + typeof(TParameter2), + typeof(TParameter3), + typeof(TParameter4), + typeof(TParameter5), + typeof(TParameter6), + typeof(TParameter7), + typeof(TParameter8), + typeof(TParameter9), + }, null); + } +} diff --git a/FastGenericNew/FastGenericNew.csproj b/FastGenericNew/FastGenericNew.csproj new file mode 100644 index 0000000..d299200 --- /dev/null +++ b/FastGenericNew/FastGenericNew.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + \ No newline at end of file diff --git a/FastGenericNew/FastNew.cs b/FastGenericNew/FastNew.cs new file mode 100644 index 0000000..34ad33d --- /dev/null +++ b/FastGenericNew/FastNew.cs @@ -0,0 +1,177 @@ +using System; +using System.Linq.Expressions; +#pragma warning disable HAA0101 // Array allocation for params parameter + +namespace FastGenericNew +{ + public static class FastNew + { + public static readonly Func CreateInstance + = Expression.Lambda>(Expression.New(ConstructorOf.value)).Compile(); + } + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1), + parameter1).Compile(); + } + } + + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2), + parameter1, parameter2).Compile(); + } + } + + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3), + parameter1, parameter2, parameter3).Compile(); + } + } + + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + ParameterExpression parameter4 = Expression.Parameter(typeof(TParameter4)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3, parameter4), + parameter1, parameter2, parameter3, parameter4).Compile(); + } + } + + public static class FastNew + { + public static readonly Func CreateInstance; + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + ParameterExpression parameter4 = Expression.Parameter(typeof(TParameter4)); + ParameterExpression parameter5 = Expression.Parameter(typeof(TParameter5)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3, parameter4, parameter5), + parameter1, parameter2, parameter3, parameter4, parameter5).Compile(); + } + } + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + ParameterExpression parameter4 = Expression.Parameter(typeof(TParameter4)); + ParameterExpression parameter5 = Expression.Parameter(typeof(TParameter5)); + ParameterExpression parameter6 = Expression.Parameter(typeof(TParameter6)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6), + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6).Compile(); + } + } + + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + ParameterExpression parameter4 = Expression.Parameter(typeof(TParameter4)); + ParameterExpression parameter5 = Expression.Parameter(typeof(TParameter5)); + ParameterExpression parameter6 = Expression.Parameter(typeof(TParameter6)); + ParameterExpression parameter7 = Expression.Parameter(typeof(TParameter7)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7), + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7).Compile(); + } + } + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + ParameterExpression parameter4 = Expression.Parameter(typeof(TParameter4)); + ParameterExpression parameter5 = Expression.Parameter(typeof(TParameter5)); + ParameterExpression parameter6 = Expression.Parameter(typeof(TParameter6)); + ParameterExpression parameter7 = Expression.Parameter(typeof(TParameter7)); + ParameterExpression parameter8 = Expression.Parameter(typeof(TParameter8)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7, parameter8), + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7, parameter8).Compile(); + } + } + + public static class FastNew + { + public static readonly Func CreateInstance; + + static FastNew() + { + ParameterExpression parameter1 = Expression.Parameter(typeof(TParameter)); + ParameterExpression parameter2 = Expression.Parameter(typeof(TParameter2)); + ParameterExpression parameter3 = Expression.Parameter(typeof(TParameter3)); + ParameterExpression parameter4 = Expression.Parameter(typeof(TParameter4)); + ParameterExpression parameter5 = Expression.Parameter(typeof(TParameter5)); + ParameterExpression parameter6 = Expression.Parameter(typeof(TParameter6)); + ParameterExpression parameter7 = Expression.Parameter(typeof(TParameter7)); + ParameterExpression parameter8 = Expression.Parameter(typeof(TParameter8)); + ParameterExpression parameter9 = Expression.Parameter(typeof(TParameter9)); + CreateInstance = Expression.Lambda>(Expression.New( + ConstructorOf.value, + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7, parameter8, parameter9), + parameter1, parameter2, parameter3, parameter4, parameter5, parameter6, parameter7, parameter8, parameter9).Compile(); + } + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..89adf4c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Boring3 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..34de0ba --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# FastGenericNew ![GitHub](https://img.shields.io/github/license/BThree496/FastGenericNew?style=flat-square) + +FastGenericNew is 10x times faster than `new T()` / `Activator.CreateInstance()` +Also with parameters support + +## Examples + +Fast create instance of `T`: + +```cs +FastNew.CreateInstance(); +``` + +Fast create instance of `T` with parameter(s): + +```cs +FastNew.CreateInstance("parameter"); +FastNew.CreateInstance("parameter", 0); +``` + +## Benchmark + +```ini + +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores +.NET Core SDK=5.0.100-rc.2.20479.15 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.47505, CoreFX 5.0.20.47505), X64 RyuJIT + DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.47505, CoreFX 5.0.20.47505), X64 RyuJIT + + +``` + +| Method | Mean | Error | StdDev | Ratio | RatioSD | Baseline | Gen 0 | Gen 1 | Gen 2 | Allocated | Code Size | +|---------- |----------:|----------:|----------:|------:|--------:|--------- |-------:|------:|------:|----------:|----------:| +| DirectNew | 1.793 ns | 0.0206 ns | 0.0193 ns | 0.79 | 0.01 | No | 0.0029 | - | - | 24 B | 25 B | +| FastNewT | 2.262 ns | 0.0076 ns | 0.0071 ns | 1.00 | 0.00 | Yes | 0.0029 | - | - | 24 B | 24 B | +| NewT | 33.332 ns | 0.3524 ns | 0.3296 ns | 14.74 | 0.16 | No | 0.0029 | - | - | 24 B | 88 B | + +## How it works + +Not like `Activator.CreateInstance()`. FastGenericNew will dynamic compile a method that return `T`. And cache it up by generic. + +You can invoke this method by a delegate with no any box/unbox. + +But there's still a little problem anyway. +.NET Runtime will not inline delegate in any case. So it cause more cost than direct new. diff --git a/meaninglessLogo.png b/meaninglessLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..109545e92cbd4221d847a529ae3028a977ce2838 GIT binary patch literal 24647 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 literal 0 HcmV?d00001