Benchmarks added & reorganized.
This commit is contained in:
1 parent
ccf5c61dd0
commit
a216c028a0
48 files changed
+13483
-363
No files matched your search
+5
-362
@@ -1,363 +1,6 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
################################################################################
|
||||||
## files generated by popular Visual Studio add-ons.
|
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
|
||||||
##
|
################################################################################
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
|
||||||
|
|
||||||
# User-specific files
|
/bin
|
||||||
*.rsuser
|
/obj
|
||||||
*.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/
|
|
||||||
[Oo]ut/
|
|
||||||
[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
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_Add()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
var list = new int[dataCount];
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list[i] = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_Add()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
var list = new List<int>();
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Add()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new PooledList<int>(ClearMode.Auto);
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Add()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new RecyclableList<int>();
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Add()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new RecyclableLongList<int>();
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_AddRangeWhenSourceIsArray()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = new int[TestObjectCount];
|
||||||
|
data.CopyTo(list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_AddRangeWhenSourceIsArray()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = new List<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_AddRangeWhenSourceIsArray()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new PooledList<int>(ClearMode.Auto);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_AddRangeWhenSourceIsArray()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableList<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_AddRangeWhenSourceIsArray()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_AddRangeWhenSourceIsIEnumerable()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsIEnumerable;
|
||||||
|
var list = new int[TestObjectCount];
|
||||||
|
int itemIndex = 0;
|
||||||
|
|
||||||
|
foreach (var item in data)
|
||||||
|
{
|
||||||
|
list[itemIndex++] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_AddRangeWhenSourceIsIEnumerable()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsIEnumerable;
|
||||||
|
var list = new List<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_AddRangeWhenSourceIsIEnumerable()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsIEnumerable;
|
||||||
|
using var list = new PooledList<int>(ClearMode.Auto);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_AddRangeWhenSourceIsIEnumerable()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsIEnumerable;
|
||||||
|
using var list = new RecyclableList<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_AddRangeWhenSourceIsIEnumerable()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsIEnumerable;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_AddRangeWhenSourceIsIList()
|
||||||
|
{
|
||||||
|
var data = (IList<int>)TestObjectsAsRecyclableLongList;
|
||||||
|
var list = new int[TestObjectCount];
|
||||||
|
data.CopyTo(list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_AddRangeWhenSourceIsIList()
|
||||||
|
{
|
||||||
|
var data = (IList<int>)TestObjectsAsRecyclableLongList;
|
||||||
|
var list = new List<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_AddRangeWhenSourceIsIList()
|
||||||
|
{
|
||||||
|
var data = (IList<int>)TestObjectsAsRecyclableLongList;
|
||||||
|
using var list = new PooledList<int>(ClearMode.Auto);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_AddRangeWhenSourceIsIList()
|
||||||
|
{
|
||||||
|
var data = (IList<int>)TestObjectsAsRecyclableLongList;
|
||||||
|
using var list = new RecyclableList<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_AddRangeWhenSourceIsIList()
|
||||||
|
{
|
||||||
|
var data = (IList<int>)TestObjectsAsRecyclableLongList;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_AddRangeWhenSourceIsList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
var list = new int[TestObjectCount];
|
||||||
|
data.CopyTo(list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_AddRangeWhenSourceIsList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
var list = new List<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_AddRangeWhenSourceIsList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
using var list = new PooledList<int>(ClearMode.Auto);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_AddRangeWhenSourceIsList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
using var list = new RecyclableList<int>();
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_AddRangeWhenSourceIsList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void PooledList_AddRangeWhenSourceIsPooledList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsPooledList;
|
||||||
|
using var list = new PooledList<int>(capacity: TestObjectCount, ClearMode.Auto);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_AddRangeWhenSourceIsRecyclableList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableList;
|
||||||
|
using var list = new RecyclableList<int>(TestObjectCount);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_AddRangeWhenSourceIsRecyclableLongList()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableList;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize, initialCapacity: TestObjectCount);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_AddRange_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
var list = new int[dataCount];
|
||||||
|
data.CopyTo(list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_AddRange_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
var list = new List<int>(dataCount);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_AddRange_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new PooledList<int>(capacity: dataCount, ClearMode.Auto);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_AddRange_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new RecyclableList<int>(dataCount);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_AddRange_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize, initialCapacity: dataCount);
|
||||||
|
list.AddRange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void List_Add_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
var list = new List<int>(dataCount);
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Add_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new PooledList<int>(capacity: dataCount, ClearMode.Auto);
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Add_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new RecyclableList<int>(dataCount);
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Add_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize, initialCapacity: dataCount);
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.Add(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_Contains_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjects;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(Array.IndexOf(list, data[i]) >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_Contains_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Contains_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Contains_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Contains_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_Contains_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjects;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_Contains_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Contains_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Contains_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Contains_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Contains(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_Count()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
DoNothing.With(data.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_Count()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
DoNothing.With(data.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Count()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsPooledList;
|
||||||
|
DoNothing.With(data.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Count()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableList;
|
||||||
|
DoNothing.With(data.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Count()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
DoNothing.With(data.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
#pragma warning disable CA1822, CA1825
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_Create()
|
||||||
|
{
|
||||||
|
var list = new int[0];
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_Create()
|
||||||
|
{
|
||||||
|
var list = new List<int>();
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Create()
|
||||||
|
{
|
||||||
|
using var list = new PooledList<int>(ClearMode.Auto);
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Create()
|
||||||
|
{
|
||||||
|
using var list = new RecyclableList<int>();
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Create()
|
||||||
|
{
|
||||||
|
using var list = new RecyclableLongList<int>();
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_Create_WithCapacity()
|
||||||
|
{
|
||||||
|
var data = new int[TestObjectCount];
|
||||||
|
DoNothing.With(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_Create_WithCapacity()
|
||||||
|
{
|
||||||
|
var list = new List<int>(TestObjectCount);
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Create_WithCapacity()
|
||||||
|
{
|
||||||
|
using var list = new PooledList<int>(capacity: TestObjectCount, ClearMode.Auto);
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Create_WithCapacity()
|
||||||
|
{
|
||||||
|
using var list = new RecyclableList<int>(TestObjectCount);
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Create_WithCapacity()
|
||||||
|
{
|
||||||
|
using var list = new RecyclableLongList<int>(minBlockSize: BlockSize, initialCapacity: TestObjectCount);
|
||||||
|
DoNothing.With(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_ForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjects)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Array_VersionedForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjects)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_ForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjectsAsList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_VersionedForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjectsAsList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_ForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjectsAsPooledList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_VersionedForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjectsAsPooledList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_ForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjectsAsRecyclableList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_VersionedForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in (IRecyclableVersionedList<int>)TestObjectsAsRecyclableList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_ForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in TestObjectsAsRecyclableLongList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_VersionedForEach()
|
||||||
|
{
|
||||||
|
foreach (var item in (IRecyclableVersionedLongList<int>)TestObjectsAsRecyclableLongList)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_GetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_GetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_GetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_GetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_GetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_GetItem_AsSpan()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
int blockSize = data.BlockSize;
|
||||||
|
int nextItemBlockIndex = data.NextItemBlockIndex;
|
||||||
|
|
||||||
|
var memoryBlocks = new Span<int[]>(data.AsArray, 0, data.LastBlockWithData + 1);
|
||||||
|
for (var blockIndex = 0; blockIndex < nextItemBlockIndex; blockIndex++)
|
||||||
|
{
|
||||||
|
var memoryBlock = new Span<int>(memoryBlocks[blockIndex], 0, blockSize);
|
||||||
|
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||||
|
{
|
||||||
|
DoNothing.With(memoryBlock[itemIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextItemBlockIndex == data.LastBlockWithData)
|
||||||
|
{
|
||||||
|
var memoryBlock = new Span<int>(memoryBlocks[nextItemBlockIndex], 0, data.NextItemIndex);
|
||||||
|
for (var itemIndex = 0; itemIndex < memoryBlock.Length; itemIndex++)
|
||||||
|
{
|
||||||
|
DoNothing.With(memoryBlock[itemIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_GetItem_AsArray()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
int blockSize = data.BlockSize;
|
||||||
|
int nextItemBlockIndex = data.NextItemBlockIndex;
|
||||||
|
|
||||||
|
var memoryBlocks = data.AsArray;
|
||||||
|
for (var blockIndex = 0; blockIndex < nextItemBlockIndex; blockIndex++)
|
||||||
|
{
|
||||||
|
var memoryBlock = memoryBlocks[blockIndex];
|
||||||
|
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||||
|
{
|
||||||
|
DoNothing.With(memoryBlock[itemIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextItemBlockIndex == data.LastBlockWithData)
|
||||||
|
{
|
||||||
|
var memoryBlock = memoryBlocks[nextItemBlockIndex];
|
||||||
|
blockSize = data.NextItemIndex;
|
||||||
|
for (var itemIndex = 0; itemIndex < blockSize; itemIndex++)
|
||||||
|
{
|
||||||
|
DoNothing.With(memoryBlock[itemIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_GetItem_AsForEach()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
foreach (var item in data)
|
||||||
|
{
|
||||||
|
DoNothing.With(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_GetItem_AsWhile()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
int dataCount = TestObjectCount;
|
||||||
|
if (dataCount == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int blockSize = data.BlockSize;
|
||||||
|
int nextItemBlockIndex = data.NextItemBlockIndex;
|
||||||
|
int itemIndex = 0;
|
||||||
|
int blockIndex = 0;
|
||||||
|
var memoryBlocks = data.AsArray;
|
||||||
|
var memoryBlock = memoryBlocks[0];
|
||||||
|
while (blockIndex < nextItemBlockIndex)
|
||||||
|
{
|
||||||
|
DoNothing.With(memoryBlock[itemIndex]);
|
||||||
|
if (itemIndex + 1 < blockSize)
|
||||||
|
{
|
||||||
|
itemIndex++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blockIndex++;
|
||||||
|
memoryBlock = memoryBlocks[blockIndex];
|
||||||
|
itemIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextItemBlockIndex == data.LastBlockWithData)
|
||||||
|
{
|
||||||
|
memoryBlock = memoryBlocks[nextItemBlockIndex];
|
||||||
|
blockSize = data.NextItemIndex;
|
||||||
|
while (itemIndex < blockSize)
|
||||||
|
{
|
||||||
|
DoNothing.With(memoryBlock[itemIndex++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_IndexOf_BestAndWorstCases()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjects;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(Array.IndexOf(list, data[i]));
|
||||||
|
DoNothing.With(Array.IndexOf(list, data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_IndexOf_BestAndWorstCases()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_IndexOf_BestAndWorstCases()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_IndexOf_BestAndWorstCases()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_IndexOf_BestAndWorstCases()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_LongIndexOf_BestAndWorstCases()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
DoNothing.With(list.LongIndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_IndexOf_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjects;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(Array.IndexOf(list, data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_IndexOf_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_IndexOf_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_IndexOf_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_IndexOf_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_LongIndexOf_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.LongIndexOf(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_IndexOf_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjects;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(Array.IndexOf(list, data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_IndexOf_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_IndexOf_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_IndexOf_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_IndexOf_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.IndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_LongIndexOf_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCountForSlowMethods;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.LongIndexOf(data[^(i + 1)]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_LongCount()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
DoNothing.With(data.LongLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_LongCount()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
DoNothing.With(data.LongCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks : DataDrivenBenchmarksBase<CollectionsBenchmarksSource>
|
||||||
|
{
|
||||||
|
protected override string GetTestMethodName(CollectionsBenchmarksSource benchmarkType) => TestCase switch
|
||||||
|
{
|
||||||
|
CollectionsBenchmarkType.AddRangeWhenSourceIsSameType => $"{benchmarkType}_AddRangeWhenSourceIs{benchmarkType}",
|
||||||
|
_ => $"{benchmarkType}_{TestCase}"
|
||||||
|
};
|
||||||
|
|
||||||
|
public RecyclableCollectionsBenchmarks()
|
||||||
|
{
|
||||||
|
TestObjectCount = 1;
|
||||||
|
//BaseDataType = RecyclableCollectionsBenchmarksSource.List;
|
||||||
|
DataType = CollectionsBenchmarksSource.RecyclableList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524_288
|
||||||
|
// 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912
|
||||||
|
// 1073741824 2147483648
|
||||||
|
|
||||||
|
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)]
|
||||||
|
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 1_000_000)]
|
||||||
|
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 100_000_000)]
|
||||||
|
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 850_000 - 1, 1_000_000, RecyclableDefaults.MaxPooledBlockSize)]
|
||||||
|
// [Params(1_000_000, 10_000_000, 100_000_000, 1_000_000_000)]
|
||||||
|
// [Params(1, 10, 64, 128, 192, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144)]
|
||||||
|
// [Params(524_288, 786_432, 1_048_576)]
|
||||||
|
// [Params(262_144, 393_216, 524_288)]
|
||||||
|
// [Params(850_000_000)]
|
||||||
|
// [Params(100_000_000)]
|
||||||
|
// [Params(RecyclableDefaults.MinItemsCountForParallelization)]
|
||||||
|
[Params(16_384)]
|
||||||
|
// [Params(127)]
|
||||||
|
// [Params(16)]
|
||||||
|
// [Params(10, 15, 128)]
|
||||||
|
// [Params(1)]
|
||||||
|
// [Params(RecyclableDefaults.MaxPooledBlockSize)]
|
||||||
|
// [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, 50, 60, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 10_000_000, 33_554_432, 50_000_000, 100_000_000)]
|
||||||
|
// *** [Params(RecyclableDefaults.MinPooledArrayLength - 3, RecyclableDefaults.MinPooledArrayLength - 2, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 2, RecyclableDefaults.MinPooledArrayLength + 3)]
|
||||||
|
// *** [Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||||
|
// *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 32, 40, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 70, 80, 90, 100, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||||
|
// [Params(256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||||
|
// [Params(RecyclableDefaults.MinItemsCountForParallelization, 1_048_576, 2_097_152, 4_194_304, 8_388_608, 16_777_216, 33_554_432, RecyclableDefaults.MaxPooledBlockSize)]
|
||||||
|
// *** [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, 40, 50, 60, 64, 70, 80, 90, 100, 127, 128)]
|
||||||
|
// [Params(1, 10, 1024, 10240, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinItemsCountForParallelization)]
|
||||||
|
// [Params(RecyclableDefaults.MinItemsCountForParallelization * 3)]
|
||||||
|
// [Params(1_048_576)]
|
||||||
|
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||||
|
|
||||||
|
[Params
|
||||||
|
(
|
||||||
|
CollectionsBenchmarksSource.Array,
|
||||||
|
CollectionsBenchmarksSource.List,
|
||||||
|
CollectionsBenchmarksSource.PooledList,
|
||||||
|
CollectionsBenchmarksSource.RecyclableList,
|
||||||
|
CollectionsBenchmarksSource.RecyclableLongList
|
||||||
|
)]
|
||||||
|
public override CollectionsBenchmarksSource DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
[Params
|
||||||
|
(
|
||||||
|
CollectionsBenchmarkType.Add_WithCapacity,
|
||||||
|
CollectionsBenchmarkType.Add,
|
||||||
|
CollectionsBenchmarkType.AddRange_WithCapacity,
|
||||||
|
CollectionsBenchmarkType.AddRangeWhenSourceIsArray,
|
||||||
|
CollectionsBenchmarkType.AddRangeWhenSourceIsIEnumerable,
|
||||||
|
CollectionsBenchmarkType.AddRangeWhenSourceIsIList,
|
||||||
|
CollectionsBenchmarkType.AddRangeWhenSourceIsList,
|
||||||
|
CollectionsBenchmarkType.AddRangeWhenSourceIsSameType,
|
||||||
|
CollectionsBenchmarkType.BinarySearch_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.Contains_FirstItems,
|
||||||
|
CollectionsBenchmarkType.Contains_LastItems,
|
||||||
|
CollectionsBenchmarkType.ConvertAll,
|
||||||
|
CollectionsBenchmarkType.Count,
|
||||||
|
CollectionsBenchmarkType.Create_WithCapacity,
|
||||||
|
CollectionsBenchmarkType.Create,
|
||||||
|
CollectionsBenchmarkType.Exists_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.Find_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.FindAll_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.FindLast_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.FindLastIndex_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.ForEach,
|
||||||
|
CollectionsBenchmarkType.GetItem,
|
||||||
|
CollectionsBenchmarkType.IndexOf_BestAndWorstCases,
|
||||||
|
CollectionsBenchmarkType.IndexOf_FirstItems,
|
||||||
|
CollectionsBenchmarkType.IndexOf_LastItems,
|
||||||
|
CollectionsBenchmarkType.LongCount,
|
||||||
|
CollectionsBenchmarkType.Remove_FirstItems,
|
||||||
|
CollectionsBenchmarkType.Remove_LastItems,
|
||||||
|
CollectionsBenchmarkType.RemoveAt_FirstItems,
|
||||||
|
CollectionsBenchmarkType.RemoveAt_LastItems,
|
||||||
|
CollectionsBenchmarkType.SetItem,
|
||||||
|
CollectionsBenchmarkType.VersionedForEach
|
||||||
|
)]
|
||||||
|
|
||||||
|
public virtual CollectionsBenchmarkType TestCase { get; set; }
|
||||||
|
|
||||||
|
public override void Setup()
|
||||||
|
{
|
||||||
|
base.Setup();
|
||||||
|
switch(TestCase)
|
||||||
|
{
|
||||||
|
case CollectionsBenchmarkType.AddRangeWhenSourceIsIList:
|
||||||
|
PrepareData(CollectionsBenchmarksSource.RecyclableLongList);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CollectionsBenchmarkType.AddRangeWhenSourceIsSameType:
|
||||||
|
PrepareData(CollectionsBenchmarksSource.RecyclableList);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void List_RemoveAt_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = new List<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_RemoveAt_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new PooledList<int>(data, ClearMode.Auto);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_RemoveAt_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableList<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_RemoveAt_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableLongList<int>(data, minBlockSize: BlockSize, initialCapacity: base.TestObjectCount);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
list.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void List_RemoveAt_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = new List<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
list.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_RemoveAt_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new PooledList<int>(data, ClearMode.Auto);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
list.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_RemoveAt_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableList<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
list.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_RemoveAt_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableLongList<int>(data, minBlockSize: BlockSize, initialCapacity: base.TestObjectCount);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
list.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void List_Remove_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = new List<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Remove_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new PooledList<int>(data, ClearMode.Auto);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Remove_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableList<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Remove_FirstItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableLongList<int>(data, minBlockSize: BlockSize, initialCapacity: base.TestObjectCount);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using Collections.Pooled;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void List_Remove_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var list = new List<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_Remove_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new PooledList<int>(data, ClearMode.Auto);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_Remove_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableList<int>(data);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_Remove_LastItems()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
using var list = new RecyclableLongList<int>(data, minBlockSize: BlockSize, initialCapacity:base.TestObjectCount);
|
||||||
|
var dataCount = TestObjectCount / 10 > 0 ? TestObjectCount / 10 : TestObjectCount;
|
||||||
|
for (var i = data.Length - 1; i > data.Length - dataCount - 1; i--)
|
||||||
|
{
|
||||||
|
DoNothing.With(list.Remove(data[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public partial class RecyclableCollectionsBenchmarks
|
||||||
|
{
|
||||||
|
public void Array_SetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
long index = 0;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[index] = TestObjects[index++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void List_SetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = TestObjects[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PooledList_SetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsPooledList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = TestObjects[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableList_SetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = TestObjects[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecyclableLongList_SetItem()
|
||||||
|
{
|
||||||
|
var data = TestObjectsAsRecyclableLongList;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (var i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = TestObjects[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
using System.Buffers;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public enum ArraySizeLimitBenchmarkType
|
||||||
|
{
|
||||||
|
ArraySizeLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArraySizeLimitBenchmarks : BaselineVsActualBenchmarkBase<ArraySizeLimitBenchmarkType>
|
||||||
|
{
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
var benchmark = new ArraySizeLimitBenchmarks();
|
||||||
|
benchmark.Setup();
|
||||||
|
FindArraySizeLimit();
|
||||||
|
benchmark.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Params(2_147_483_605)]
|
||||||
|
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = 1)]
|
||||||
|
public void Max_Allowed_Size_2_147_483_605()
|
||||||
|
{
|
||||||
|
long[] arr = ArrayPool<long>.Shared.Rent(TestObjectCount);
|
||||||
|
DoNothing.With(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(OperationsPerInvoke = 1)]
|
||||||
|
public static void FindArraySizeLimit()
|
||||||
|
{
|
||||||
|
var pool = ArrayPool<long>.Shared;
|
||||||
|
var bufferSize = int.MaxValue / 2;
|
||||||
|
var oldValue = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.Write($"Allocating {bufferSize}...");
|
||||||
|
var arr = pool.Rent(bufferSize);
|
||||||
|
Console.WriteLine("success");
|
||||||
|
pool.Return(arr);
|
||||||
|
arr = null;
|
||||||
|
|
||||||
|
var nextValue = bufferSize - oldValue;
|
||||||
|
oldValue = bufferSize;
|
||||||
|
bufferSize = checked(bufferSize + nextValue);
|
||||||
|
|
||||||
|
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Console.WriteLine("error");
|
||||||
|
var nextValue = (bufferSize - oldValue) >> 1;
|
||||||
|
if (nextValue == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferSize = oldValue + nextValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("All done");
|
||||||
|
throw new Exception($"Everything was successful. You can create {oldValue} byte big arrays. Exception is logged to prevent more benchmarks.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public enum BoolOrCompareBenchmarkType
|
||||||
|
{
|
||||||
|
Bool,
|
||||||
|
Compare,
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class BoolOrCompareBenchmarks : BaselineVsActualBenchmarkBase<BoolOrCompareBenchmarkType>
|
||||||
|
{
|
||||||
|
[Params(BoolOrCompareBenchmarkType.Bool, BoolOrCompareBenchmarkType.Compare)]
|
||||||
|
public override BoolOrCompareBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
[Params(8)]
|
||||||
|
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||||
|
|
||||||
|
[Params(true)]
|
||||||
|
public bool TestBool = true;
|
||||||
|
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
var benchmark = new BoolOrCompareBenchmarks();
|
||||||
|
benchmark.Setup();
|
||||||
|
benchmark.Bool();
|
||||||
|
benchmark.Compare();
|
||||||
|
benchmark.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Bool()
|
||||||
|
{
|
||||||
|
if (TestBool)
|
||||||
|
{
|
||||||
|
DoNothing.With(TestBool);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoNothing.With(TestBool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Compare()
|
||||||
|
{
|
||||||
|
if (TestObjectCount >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
DoNothing.With(TestBool);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoNothing.With(TestBool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Action? GetTestMethod(BoolOrCompareBenchmarkType benchmarkType) => benchmarkType switch
|
||||||
|
{
|
||||||
|
BoolOrCompareBenchmarkType.Bool => Bool,
|
||||||
|
BoolOrCompareBenchmarkType.Compare => Compare,
|
||||||
|
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
// Ignore Spelling: Poc Structs Unboxed Funcs Comparers
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public enum DelegateVsComparerBenchmarkType
|
||||||
|
{
|
||||||
|
Comparer,
|
||||||
|
Delegate,
|
||||||
|
Func,
|
||||||
|
ListOfBoxedStructs,
|
||||||
|
ListOfClasses,
|
||||||
|
ListOfComparers,
|
||||||
|
ListOfDelegates,
|
||||||
|
ListOfFuncs,
|
||||||
|
ListOfLocalFuncs,
|
||||||
|
ListOfStructs,
|
||||||
|
ListOfUnboxedReadOnlyStructs,
|
||||||
|
ListOfUnboxedStructs,
|
||||||
|
StaticFunc,
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class DelegateVsComparerBenchmarks : BaselineVsActualBenchmarkBase<DelegateVsComparerBenchmarkType>
|
||||||
|
{
|
||||||
|
[Params
|
||||||
|
(
|
||||||
|
DelegateVsComparerBenchmarkType.Delegate,
|
||||||
|
DelegateVsComparerBenchmarkType.Func,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfBoxedStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfClasses,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfComparers,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfDelegates,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfFuncs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfLocalFuncs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfUnboxedReadOnlyStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfUnboxedStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.StaticFunc
|
||||||
|
)]
|
||||||
|
public override DelegateVsComparerBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
[Params(DelegateVsComparerBenchmarkType.Comparer)]
|
||||||
|
public override DelegateVsComparerBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||||
|
|
||||||
|
#region Dummy classes
|
||||||
|
|
||||||
|
private delegate T Compare<T>(T x, T y);
|
||||||
|
|
||||||
|
public readonly struct MyComparerReadOnlyStruct<T> : IComparer<T>
|
||||||
|
{
|
||||||
|
public int Compare(T? x, T? y) => Comparer<T>.Default.Compare(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct MyComparerStruct<T> : IComparer<T>
|
||||||
|
{
|
||||||
|
public readonly int Compare(T? x, T? y) => Comparer<T>.Default.Compare(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyComparer : IComparer<long>
|
||||||
|
{
|
||||||
|
public int Compare(long x, long y) => (x - y) switch
|
||||||
|
{
|
||||||
|
> 0 => 1,
|
||||||
|
< 0 => -1,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
var benchmark = new DelegateVsComparerBenchmarks();
|
||||||
|
benchmark.Setup();
|
||||||
|
benchmark.Comparer();
|
||||||
|
benchmark.Delegate();
|
||||||
|
benchmark.Func();
|
||||||
|
benchmark.ListOfBoxedStructs();
|
||||||
|
benchmark.ListOfClasses();
|
||||||
|
benchmark.ListOfComparers();
|
||||||
|
benchmark.ListOfDelegates();
|
||||||
|
benchmark.ListOfFuncs();
|
||||||
|
benchmark.ListOfLocalFuncs();
|
||||||
|
benchmark.ListOfStructs();
|
||||||
|
benchmark.ListOfUnboxedReadOnlyStructs();
|
||||||
|
benchmark.ListOfUnboxedStructs();
|
||||||
|
benchmark.StaticFunc();
|
||||||
|
benchmark.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Comparer<long> _comparer = Comparer<long>.Default;
|
||||||
|
private IEnumerable<long>? _testObjects;
|
||||||
|
private IEnumerable<Func<long, long, int>>? _testListOfFunctions;
|
||||||
|
private IEnumerable<IComparer<long>>? _testListOfComparers;
|
||||||
|
private IEnumerable<Compare<long>>? _testListOfDelegates;
|
||||||
|
private IEnumerable<Func<long, long, int>>? _testListOfLocalFunctions;
|
||||||
|
private IEnumerable<MyComparer>? _testListOfClasses;
|
||||||
|
private IEnumerable<MyComparerStruct<long>>? _testListOfStructs;
|
||||||
|
private IEnumerable<IComparer<long>>? _testListOfBoxedStructs;
|
||||||
|
private IEnumerable<TComparer> TestListOfUnboxedStructs<TComparer, TValue>() where TComparer : IComparer<TValue>, new()
|
||||||
|
{
|
||||||
|
foreach (var _ in _testObjects!)
|
||||||
|
{
|
||||||
|
yield return new TComparer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<Func<long, long, int>> GetLocalFunctions(IEnumerable<long> testObjects)
|
||||||
|
{
|
||||||
|
static int compareFunc(long x, long y)
|
||||||
|
{
|
||||||
|
return (x - y) switch
|
||||||
|
{
|
||||||
|
> 0 => 1,
|
||||||
|
< 0 => -1,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var _ in testObjects)
|
||||||
|
{
|
||||||
|
yield return compareFunc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestWithComparer(IComparer<long> comparer)
|
||||||
|
{
|
||||||
|
var testData = _testObjects!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||||
|
{
|
||||||
|
_ = comparer.Compare(testData[itemIdx], testData[itemIdx + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestWithDelegate(Compare<long> compareFunc)
|
||||||
|
{
|
||||||
|
var testData = _testObjects!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||||
|
{
|
||||||
|
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestWithFunc(Func<long, long, int> compareFunc)
|
||||||
|
{
|
||||||
|
var testData = _testObjects!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length - 1; itemIdx++)
|
||||||
|
{
|
||||||
|
_ = compareFunc(testData[itemIdx], testData[itemIdx + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Comparer()
|
||||||
|
{
|
||||||
|
TestWithComparer(_comparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Func()
|
||||||
|
{
|
||||||
|
TestWithFunc((x, y) => (x - y) switch
|
||||||
|
{
|
||||||
|
> 0 => 1,
|
||||||
|
< 0 => -1,
|
||||||
|
_ => 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StaticFunc()
|
||||||
|
{
|
||||||
|
TestWithFunc(static (x, y) => (x - y) switch
|
||||||
|
{
|
||||||
|
> 0 => 1,
|
||||||
|
< 0 => -1,
|
||||||
|
_ => 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delegate()
|
||||||
|
{
|
||||||
|
TestWithDelegate((x, y) => (x - y) switch
|
||||||
|
{
|
||||||
|
> 0 => 1,
|
||||||
|
< 0 => -1,
|
||||||
|
_ => 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfFuncs()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfFunctions!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var compareFunc = testData[itemIdx];
|
||||||
|
_ = compareFunc(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfLocalFuncs()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfLocalFunctions!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var compareFunc = testData[itemIdx];
|
||||||
|
_ = compareFunc(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfComparers()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfComparers!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var comparer = testData[itemIdx];
|
||||||
|
_ = comparer.Compare(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfClasses()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfClasses!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var comparer = testData[itemIdx];
|
||||||
|
_ = comparer.Compare(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfStructs()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfStructs!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var comparer = testData[itemIdx];
|
||||||
|
_ = comparer.Compare(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfBoxedStructs()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfBoxedStructs!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var comparer = testData[itemIdx];
|
||||||
|
_ = comparer.Compare(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfUnboxedStructs()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = TestListOfUnboxedStructs<MyComparerStruct<long>, long>().ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var comparer = testData[itemIdx];
|
||||||
|
_ = comparer.Compare(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfUnboxedReadOnlyStructs()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = TestListOfUnboxedStructs<MyComparerReadOnlyStruct<long>, long>().ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var comparer = testData[itemIdx];
|
||||||
|
_ = comparer.Compare(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ListOfDelegates()
|
||||||
|
{
|
||||||
|
const long X = 2, Y = 5;
|
||||||
|
var testData = _testListOfDelegates!.ToArray();
|
||||||
|
for (var itemIdx = 0; itemIdx < testData.Length; itemIdx++)
|
||||||
|
{
|
||||||
|
var compareDelegate = testData[itemIdx];
|
||||||
|
_ = compareDelegate(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Action? GetTestMethod(DelegateVsComparerBenchmarkType benchmarkType) => benchmarkType switch
|
||||||
|
{
|
||||||
|
DelegateVsComparerBenchmarkType.Comparer => Comparer,
|
||||||
|
DelegateVsComparerBenchmarkType.Delegate => Delegate,
|
||||||
|
DelegateVsComparerBenchmarkType.Func => Func,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfBoxedStructs => ListOfBoxedStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfClasses => ListOfClasses,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfComparers => ListOfComparers,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfDelegates => ListOfDelegates,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfFuncs => ListOfFuncs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfLocalFuncs => ListOfLocalFuncs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfStructs => ListOfStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfUnboxedReadOnlyStructs => ListOfUnboxedReadOnlyStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.ListOfUnboxedStructs => ListOfUnboxedStructs,
|
||||||
|
DelegateVsComparerBenchmarkType.StaticFunc => StaticFunc,
|
||||||
|
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||||
|
};
|
||||||
|
|
||||||
|
public override void Setup()
|
||||||
|
{
|
||||||
|
Console.WriteLine("******* SETTING UP COMMON TEST DATA *******");
|
||||||
|
_testObjects = Enumerable.Range(1, TestObjectCount).Select(x => (long)x);
|
||||||
|
base.Setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Cleanup()
|
||||||
|
{
|
||||||
|
_testObjects = null;
|
||||||
|
base.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PrepareData<T>(T benchmarkType)
|
||||||
|
{
|
||||||
|
switch (benchmarkType)
|
||||||
|
{
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfBoxedStructs:
|
||||||
|
_testListOfBoxedStructs = _testObjects!.Select(_ => (IComparer<long>)new MyComparerStruct<long>());
|
||||||
|
break;
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfClasses:
|
||||||
|
_testListOfClasses = _testObjects!.Select(_ => new MyComparer());
|
||||||
|
break;
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfComparers:
|
||||||
|
_testListOfComparers = _testObjects!.Select(_ => (IComparer<long>)new MyComparer());
|
||||||
|
break;
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfDelegates:
|
||||||
|
_testListOfDelegates = _testObjects!.Select(_ => new Compare<long>((x, y) => new MyComparer().Compare(x, y)));
|
||||||
|
break;
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfFuncs:
|
||||||
|
_testListOfFunctions = _testObjects!.Select<long, Func<long, long, int>>(static _ => new MyComparer().Compare);
|
||||||
|
break;
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfLocalFuncs:
|
||||||
|
_testListOfLocalFunctions = GetLocalFunctions(_testObjects!);
|
||||||
|
break;
|
||||||
|
case DelegateVsComparerBenchmarkType.ListOfStructs:
|
||||||
|
_testListOfStructs = _testObjects!.Select(_ => new MyComparerStruct<long>());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Recyclable.Collections.TestData;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
|
||||||
|
public class EqualVsContainsInConsecutiveOrderBenchmarks : IDisposable
|
||||||
|
{
|
||||||
|
private const int TestItemsCount = 10000;
|
||||||
|
|
||||||
|
private readonly IEnumerable<long> _list1 = RecyclableLongListTestData.CreateTestData(TestItemsCount).ToRecyclableList();
|
||||||
|
private readonly IEnumerable<long> _list2 = RecyclableLongListTestData.CreateTestData(TestItemsCount).ToArray();
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void Equal()
|
||||||
|
{
|
||||||
|
_ = _list1.Should().Equal(_list2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void ContainsInConsecutiveOrder()
|
||||||
|
{
|
||||||
|
_ = _list1.Should().ContainInConsecutiveOrder(_list2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose()
|
||||||
|
{
|
||||||
|
if (_list1 is IDisposable disposable1)
|
||||||
|
{
|
||||||
|
disposable1.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_list2 is IDisposable disposable2)
|
||||||
|
{
|
||||||
|
disposable2.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
#pragma warning disable CA1822 // Mark members as static
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public class GreaterOperatorVsNotEqualOperatorBenchmarks
|
||||||
|
{
|
||||||
|
private static readonly long _num = RecyclableDefaults.MinItemsCountForParallelization;
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"*** We're comparing if {_num} is < 0 ***");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void CompareWithGreater()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num > 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareWithGreaterEqual()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num >= 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareWithNotEqual()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareWithLess()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num < 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareWithEqual()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num == 0 ? 0 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
#pragma warning disable CA1822
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public class LessOperatorVsAndOperatorBenchmarks
|
||||||
|
{
|
||||||
|
private const int BitShift = 1 << 31;
|
||||||
|
private static readonly Random _rnd = new(1);
|
||||||
|
private static int _num = -Math.Abs(_rnd.Next());
|
||||||
|
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_num = -1;
|
||||||
|
Console.WriteLine($"*** We're comparing if {_num} is < 0 ***");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cleanup() { }
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void CompareWithLess()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareWithAnd()
|
||||||
|
{
|
||||||
|
DoNothing.With((_num & BitShift) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareWithEqual()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CompareToZero()
|
||||||
|
{
|
||||||
|
DoNothing.With(_num == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,371 @@
|
|||||||
|
// Ignore Spelling: Mul Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class ModuloBenchmarks
|
||||||
|
{
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
var benchmark = new ModuloBenchmarks();
|
||||||
|
benchmark.Setup();
|
||||||
|
benchmark.AddWithFor();
|
||||||
|
benchmark.AddWithForOptimized();
|
||||||
|
benchmark.DividerAndModulusWithOperator();
|
||||||
|
benchmark.MathDivRem();
|
||||||
|
benchmark.MixedApproachWithForLoopOptimized();
|
||||||
|
benchmark.MixedApproachWithSubtractWithStackalloc();
|
||||||
|
benchmark.MixedApproachWithSubtractWithWhile();
|
||||||
|
benchmark.MixedApproachWithSubtractWithWhileAsVector();
|
||||||
|
benchmark.MixedApproachWithSubtractWithWhileWithSse2();
|
||||||
|
benchmark.SubtractWithWhile();
|
||||||
|
benchmark.SubtractWithWhileWithSse2();
|
||||||
|
benchmark.XDivYMulX();
|
||||||
|
benchmark.XDivYMulXWithLocalVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long _cutoff;
|
||||||
|
private Vector128<long> _increment;
|
||||||
|
private long _lastCaseIndex;
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_cutoff = checked((long)BlockSize << 4);
|
||||||
|
_increment = Vector128.Create(-BlockSize, 1L);
|
||||||
|
_lastCaseIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Params(123, 10, 2, int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 10, int.MaxValue / 15, int.MaxValue / 20)]
|
||||||
|
[Params(int.MaxValue, int.MaxValue / 2, int.MaxValue / 3, int.MaxValue / 4, int.MaxValue / 6, int.MaxValue / 8, int.MaxValue / 10, int.MaxValue / 100)]
|
||||||
|
//[Params(int.MaxValue / 10, int.MaxValue / 20, int.MaxValue / 100)]
|
||||||
|
public int BlockSize { get; set; } = int.MaxValue;
|
||||||
|
|
||||||
|
[Params(int.MaxValue, int.MaxValue / 1000, int.MaxValue / 10000)]
|
||||||
|
//[Params(int.MaxValue)]
|
||||||
|
//[Params(int.MaxValue * 100L)]
|
||||||
|
public long TestNumber { get; set; } = int.MaxValue;
|
||||||
|
|
||||||
|
private void CalculateDividerAndModulusWithOperator(long i)
|
||||||
|
{
|
||||||
|
DoNothing.With(i / BlockSize, i % BlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithMathDivRem(long i)
|
||||||
|
{
|
||||||
|
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithAddWithFor(long i)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int remainder = 0;
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
for (long iteration = 0; iteration < i; iteration++)
|
||||||
|
{
|
||||||
|
if (remainder > blockSize - 1)
|
||||||
|
{
|
||||||
|
remainder = 0;
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
remainder++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(result, remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithAddWithForOptimized(long i)
|
||||||
|
{
|
||||||
|
long total = 0;
|
||||||
|
int result = 0;
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
while (total + blockSize <= i)
|
||||||
|
{
|
||||||
|
total += blockSize;
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(result, i - total);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithXDivYMulX(long i)
|
||||||
|
{
|
||||||
|
DoNothing.With(i / BlockSize, i - (i / BlockSize * BlockSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithXDivYMulXWithLocalVar(long i)
|
||||||
|
{
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
int result = (int)(i / blockSize);
|
||||||
|
DoNothing.With(result, i - (result * blockSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithSubtractWithWhile(long i)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
long remainder = i;
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
while (remainder >= blockSize)
|
||||||
|
{
|
||||||
|
remainder -= blockSize;
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(result, remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithSubtractWithWhileWithSse2(long i)
|
||||||
|
{
|
||||||
|
var state = Vector128.Create(i, 0);
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
var inc = _increment;
|
||||||
|
while (state.GetElement(0) >= blockSize)
|
||||||
|
{
|
||||||
|
state = Sse2.Add(state, inc);
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(state.GetElement(1), state.GetElement(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithMixedApproachWithSubtractWithWhile(long i)
|
||||||
|
{
|
||||||
|
long remainder;
|
||||||
|
if (i >= _cutoff)
|
||||||
|
{
|
||||||
|
DoNothing.With(Math.DivRem(i, BlockSize, out remainder), remainder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
remainder = i;
|
||||||
|
while (remainder >= blockSize)
|
||||||
|
{
|
||||||
|
remainder -= blockSize;
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(result, remainder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithMixedApproachWithSubtractWithWhileAsVector(long i)
|
||||||
|
{
|
||||||
|
if (i >= _cutoff)
|
||||||
|
{
|
||||||
|
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var state = new Vector<long>(new[] { 0L, i, 0, 0 });
|
||||||
|
var increment = new Vector<long>(new[] { 1L, -BlockSize, 0, 0 });
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
while (state[1] >= blockSize)
|
||||||
|
{
|
||||||
|
state += increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(state[0], state[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithMixedApproachWithSubtractWithWhileWithSse2(long i)
|
||||||
|
{
|
||||||
|
if (i >= _cutoff)
|
||||||
|
{
|
||||||
|
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var increment = _increment;
|
||||||
|
var state = Vector128.Create(i, 0);
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
while (state.GetElement(0) >= blockSize)
|
||||||
|
{
|
||||||
|
state = Sse2.Add(state, increment);
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(state.GetElement(1), state.GetElement(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithMixedApproachWithSubtractWithStackalloc(long i)
|
||||||
|
{
|
||||||
|
if (i >= _cutoff)
|
||||||
|
{
|
||||||
|
DoNothing.With(Math.DivRem(i, BlockSize, out long remainder), remainder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Span<long> state = stackalloc long[2] { i, 0 };// Vector128.Create(BlockSize, 0);
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
while (state[0] >= blockSize)
|
||||||
|
{
|
||||||
|
state[0] -= blockSize;
|
||||||
|
state[1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(state[1], state[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateWithMixedApproachWithForLoopOptimized(long i)
|
||||||
|
{
|
||||||
|
long total;
|
||||||
|
if (i >= _cutoff)
|
||||||
|
{
|
||||||
|
DoNothing.With(Math.DivRem(i, BlockSize, out total), total);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
total = 0;
|
||||||
|
int result = 0;
|
||||||
|
int blockSize = BlockSize;
|
||||||
|
while (total + blockSize <= i)
|
||||||
|
{
|
||||||
|
total += blockSize;
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoNothing.With(result, i - total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void DividerAndModulusWithOperator()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateDividerAndModulusWithOperator(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void MathDivRem()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithMathDivRem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void AddWithFor()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithAddWithFor(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void AddWithForOptimized()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithAddWithForOptimized(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void XDivYMulX()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithXDivYMulX(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void XDivYMulXWithLocalVar()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithXDivYMulXWithLocalVar(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void SubtractWithWhile()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithSubtractWithWhile(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void SubtractWithWhileWithSse2()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithSubtractWithWhileWithSse2(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void MixedApproachWithSubtractWithWhile()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithMixedApproachWithSubtractWithWhile(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void MixedApproachWithSubtractWithWhileAsVector()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithMixedApproachWithSubtractWithWhileAsVector(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void MixedApproachWithSubtractWithWhileWithSse2()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithMixedApproachWithSubtractWithWhileWithSse2(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void MixedApproachWithSubtractWithStackalloc()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithMixedApproachWithSubtractWithStackalloc(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void MixedApproachWithForLoopOptimized()
|
||||||
|
{
|
||||||
|
long testNumber = TestNumber;
|
||||||
|
for (long i = testNumber; i >= _lastCaseIndex; i--)
|
||||||
|
{
|
||||||
|
CalculateWithMixedApproachWithForLoopOptimized(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
BenchmarkDotNet=v0.13.3, OS=ubuntu 20.04
|
||||||
|
Intel Xeon Platinum 8272CL CPU 2.60GHz, 1 CPU, 4 logical and 2 physical cores
|
||||||
|
.NET SDK=7.0.203
|
||||||
|
[Host] : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
|
||||||
|
DefaultJob : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
|
||||||
|
|
||||||
|
|
||||||
|
| Method | Mean | Error | StdDev | Ratio | RatioSD |
|
||||||
|
|------------------------- |--------:|---------:|---------:|------:|--------:|
|
||||||
|
| RecyclableLongList_IndexOfV1 | 2.274 s | 0.0447 s | 0.0894 s | 1.00 | 0.04 |
|
||||||
|
| RecyclableLongList_IndexOfV2 | 2.302 s | 0.0456 s | 0.0750 s | 1.00 | 0.00 |
|
||||||
|
| RecyclableLongList_IndexOf | 2.234 s | 0.0446 s | 0.0681 s | 0.97 | 0.05 |
|
||||||
|
|
||||||
|
// * Hints *
|
||||||
|
Outliers
|
||||||
|
RecyclableLongListPocBenchmarks.RecyclableLongList_IndexOfV2: Default -> 2 outliers were removed (2.54 s, 2.56 s)
|
||||||
|
RecyclableLongListPocBenchmarks.RecyclableLongList_IndexOf: Default -> 1 outlier was detected (2.06 s)
|
||||||
|
|
||||||
|
// * Legends *
|
||||||
|
Mean : Arithmetic mean of all measurements
|
||||||
|
Error : Half of 99.9% confidence interval
|
||||||
|
StdDev : Standard deviation of all measurements
|
||||||
|
Ratio : Mean of the ratio distribution ([Current]/[Baseline])
|
||||||
|
RatioSD : Standard deviation of the ratio distribution ([Current]/[Baseline])
|
||||||
|
1 s : 1 Second (1 sec)
|
||||||
|
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
// Ignore Spelling: POC
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Pooled;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public partial class RecyclableLongListBenchmarks<T> : BaselineVsActualBenchmarkBase<T>
|
||||||
|
{
|
||||||
|
private int[]? _testArray;
|
||||||
|
public int[] TestObjects => _testArray ?? throw new NullReferenceException("Something is wrong and test objects are null");
|
||||||
|
|
||||||
|
public RecyclableLongList<int> TestObjectsAsRecyclableLongList => _testRecyclableLongList ?? throw new NullReferenceException($"Something is wrong and {nameof(RecyclableLongList<int>)} is null");
|
||||||
|
private RecyclableLongList<int>? _testRecyclableLongList;
|
||||||
|
private PooledList<int>? _testPooledList;
|
||||||
|
internal PooledList<int> TestPooledList => _testPooledList ?? throw new NullReferenceException($"Something is wrong and {nameof(PooledList<int>)} is null");
|
||||||
|
|
||||||
|
private static readonly MethodInfo _ensureCapacityNewFunc;
|
||||||
|
|
||||||
|
static RecyclableLongListBenchmarks()
|
||||||
|
{
|
||||||
|
_ensureCapacityNewFunc = typeof(RecyclableLongList<int>).GetMethod("EnsureCapacity", BindingFlags.Static | BindingFlags.NonPublic)
|
||||||
|
?? throw new NullReferenceException($"Method EnsureCapacity not found in class {nameof(RecyclableLongList<int>)}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Setup()
|
||||||
|
{
|
||||||
|
Console.WriteLine("******* SETTING UP EXPECTED RESULTS DATA *******");
|
||||||
|
_testArray = DataGenerator.EnumerateTestObjects(TestObjectCount);
|
||||||
|
|
||||||
|
base.Setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Cleanup()
|
||||||
|
{
|
||||||
|
_testArray = null;
|
||||||
|
_testRecyclableLongList?.Dispose();
|
||||||
|
_testRecyclableLongList = null;
|
||||||
|
_testPooledList?.Dispose();
|
||||||
|
_testPooledList = null;
|
||||||
|
|
||||||
|
base.Cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//[MemoryDiagnoser]
|
||||||
|
//public class ListVsLinkedListBenchmarks
|
||||||
|
//{
|
||||||
|
// [Benchmark]
|
||||||
|
// public void RecyclableList()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// using var list = new RecyclableList<object>(initialCapacity: dataCount);
|
||||||
|
// for (int i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Add(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < list.LongCount; i++)
|
||||||
|
// {
|
||||||
|
// DoNothing(list[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Benchmark(Baseline = true)]
|
||||||
|
// public void RecyclableLongList()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// int dataCount = TestObjectCount;
|
||||||
|
// using var list = new RecyclableLongList<object>(BlockSize, totalItemsCount: dataCount);
|
||||||
|
// for (int i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Add(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < list.LongCount; i++)
|
||||||
|
// {
|
||||||
|
// DoNothing(list[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void List()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new List<object>(capacity: dataCount);
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Add(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (var i = 0; i < list.Count; i++)
|
||||||
|
// {
|
||||||
|
// DoNothing(list[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void LinkedList()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new LinkedList<object>();
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// _ = list.AddLast(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// foreach (var node in list)
|
||||||
|
// {
|
||||||
|
// DoNothing(node);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void RecyclableQueue()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new RecyclableQueue<object>(BlockSize);
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Enqueue(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (list.LongCount > 0)
|
||||||
|
// {
|
||||||
|
// DoNothing(list.Dequeue());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void Queue()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new Queue<object>(capacity: dataCount);
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Enqueue(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (list.Count > 0)
|
||||||
|
// {
|
||||||
|
// DoNothing(list.Dequeue());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void PriorityQueue()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new PriorityQueue<object, int>(initialCapacity: dataCount);
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Enqueue(data[i], i);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (list.Count > 0)
|
||||||
|
// {
|
||||||
|
// DoNothing(list.Dequeue());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void RecyclableSortedList_InUpdateMode()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new RecyclableSortedList<int, object>(BlockSize);
|
||||||
|
// list.BeginUpdate();
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Add(i, data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.EndUpdate();
|
||||||
|
|
||||||
|
// for (var i = 0; i < list.LongCount; i++)
|
||||||
|
// {
|
||||||
|
// DoNothing(list[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void RecyclableSortedList()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new RecyclableSortedList<int, object>(BlockSize);
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Add(i, data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (var i = 0; i < list.LongCount; i++)
|
||||||
|
// {
|
||||||
|
// DoNothing(list[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void SortedList()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new SortedList<int, object>();
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Add(i, data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (var i = 0; i < list.Count; i++)
|
||||||
|
// {
|
||||||
|
// DoNothing(list[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void RecyclableStack()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new RecyclableStack<object>(BlockSize);
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Push(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (list.LongCount > 0)
|
||||||
|
// {
|
||||||
|
// DoNothing(list.Pop());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //[Benchmark]
|
||||||
|
// public void Stack()
|
||||||
|
// {
|
||||||
|
// var data = TestObjects;
|
||||||
|
// var dataCount = TestObjectCount;
|
||||||
|
// var list = new Stack<object>();
|
||||||
|
// for (var i = 0; i < dataCount; i++)
|
||||||
|
// {
|
||||||
|
// list.Push(data[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (list.Count > 0)
|
||||||
|
// {
|
||||||
|
// DoNothing(list.Pop());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// list.Clear();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
@@ -0,0 +1,360 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public class RefVsInstanceMemberBenchmarks
|
||||||
|
{
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
var benchmark = new RefVsInstanceMemberBenchmarks();
|
||||||
|
benchmark.ArrayInstanceMember2();
|
||||||
|
benchmark.ArrayInstanceMember3();
|
||||||
|
benchmark.ArrayInstanceMember4();
|
||||||
|
benchmark.ArrayInstanceMember5();
|
||||||
|
benchmark.ArrayInstanceMember6();
|
||||||
|
benchmark.ArrayInstanceMemberLocalVar5();
|
||||||
|
benchmark.ArrayInstanceMemberLocalVar6();
|
||||||
|
benchmark.IntInstanceMember2();
|
||||||
|
benchmark.IntInstanceMember3();
|
||||||
|
benchmark.IntInstanceMember4();
|
||||||
|
benchmark.IntInstanceMember5();
|
||||||
|
benchmark.RefToArray2();
|
||||||
|
benchmark.RefToArray3();
|
||||||
|
benchmark.RefToArray4();
|
||||||
|
benchmark.RefToArray5();
|
||||||
|
benchmark.RefToArray6();
|
||||||
|
benchmark.RefToInt2();
|
||||||
|
benchmark.RefToInt3();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly TestCase _testCase = new();
|
||||||
|
private class TestCase
|
||||||
|
{
|
||||||
|
private int[] _items = new int[123];
|
||||||
|
private int _count = 123;
|
||||||
|
private static int Add(int count)
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get => _count;
|
||||||
|
set => _count = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int GetCountAsRefCount2()
|
||||||
|
{
|
||||||
|
ref int count = ref _count;
|
||||||
|
count = 234;
|
||||||
|
return ref count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int GetCountAsRefCount3()
|
||||||
|
{
|
||||||
|
ref int count = ref _count;
|
||||||
|
count = 234;
|
||||||
|
_ = TestCase.Add(count);
|
||||||
|
return ref count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int GetCountAsRefCount4()
|
||||||
|
{
|
||||||
|
ref int count = ref _count;
|
||||||
|
count = 234;
|
||||||
|
_ = TestCase.Add(count);
|
||||||
|
_ = TestCase.Add(count);
|
||||||
|
return ref count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref int GetCountAsRefCount5()
|
||||||
|
{
|
||||||
|
ref int count = ref _count;
|
||||||
|
count = 234;
|
||||||
|
_ = TestCase.Add(count);
|
||||||
|
_ = TestCase.Add(count);
|
||||||
|
_ = TestCase.Add(count);
|
||||||
|
return ref count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetCountAsInstanceMember2()
|
||||||
|
{
|
||||||
|
_count = 234;
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetCountAsInstanceMember3()
|
||||||
|
{
|
||||||
|
_count = 234;
|
||||||
|
_ = TestCase.Add(_count);
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetCountAsInstanceMember4()
|
||||||
|
{
|
||||||
|
_count = 234;
|
||||||
|
_ = TestCase.Add(_count);
|
||||||
|
_ = TestCase.Add(_count);
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetCountAsInstanceMember5()
|
||||||
|
{
|
||||||
|
_count = 234;
|
||||||
|
_ = TestCase.Add(_count);
|
||||||
|
_ = TestCase.Add(_count);
|
||||||
|
_ = TestCase.Add(_count);
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArray2()
|
||||||
|
{
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
return _items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArray3()
|
||||||
|
{
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
return _items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArray4()
|
||||||
|
{
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
return _items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArray5()
|
||||||
|
{
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
return _items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArray6()
|
||||||
|
{
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
_ = TestCase.Add(_items.Length);
|
||||||
|
return _items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArrayLocalVar5()
|
||||||
|
{
|
||||||
|
var items = _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsArrayLocalVar6()
|
||||||
|
{
|
||||||
|
var items = _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsRefArray2()
|
||||||
|
{
|
||||||
|
ref int[] items = ref _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsRefArray3()
|
||||||
|
{
|
||||||
|
ref int[] items = ref _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsRefArray4()
|
||||||
|
{
|
||||||
|
ref int[] items = ref _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsRefArray5()
|
||||||
|
{
|
||||||
|
ref int[] items = ref _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetLengthAsRefArray6()
|
||||||
|
{
|
||||||
|
ref int[] items = ref _items;
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
_ = TestCase.Add(items.Length);
|
||||||
|
return items.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToInt2()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsRefCount2();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToInt3()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsRefCount3();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToInt4()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsRefCount4();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToInt5()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsRefCount5();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void IntInstanceMember2()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsInstanceMember2();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void IntInstanceMember3()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsInstanceMember3();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void IntInstanceMember4()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsInstanceMember4();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void IntInstanceMember5()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetCountAsInstanceMember5();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToArray2()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsRefArray2();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToArray3()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsRefArray3();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToArray4()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsRefArray4();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToArray5()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsRefArray5();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void RefToArray6()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsRefArray6();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMember2()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArray2();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMember3()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArray3();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMember4()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArray4();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMember5()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArray5();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMember6()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArray6();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMemberLocalVar5()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArrayLocalVar5();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = false)]
|
||||||
|
public void ArrayInstanceMemberLocalVar6()
|
||||||
|
{
|
||||||
|
var count = _testCase.GetLengthAsArrayLocalVar6();
|
||||||
|
DoNothing.With(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public enum RoundBenchmarkType
|
||||||
|
{
|
||||||
|
MathFloor,
|
||||||
|
MathRound,
|
||||||
|
WithTypecasting,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoundBenchmarks : BaselineVsActualBenchmarkBase<RoundBenchmarkType>
|
||||||
|
{
|
||||||
|
[Params(RoundBenchmarkType.MathFloor)]
|
||||||
|
public override RoundBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||||
|
|
||||||
|
[Params(RoundBenchmarkType.MathRound, RoundBenchmarkType.WithTypecasting)]
|
||||||
|
public override RoundBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
private const double OptimalParallelSearchStep = 0.329;
|
||||||
|
|
||||||
|
public void RoundWithMathFloor()
|
||||||
|
{
|
||||||
|
DoNothing.With((long)Math.Floor(TestObjectCount * OptimalParallelSearchStep));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RoundWithMathRound()
|
||||||
|
{
|
||||||
|
DoNothing.With((long)Math.Round(TestObjectCount * OptimalParallelSearchStep, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RoundWithTypeCasting()
|
||||||
|
{
|
||||||
|
DoNothing.With((long)(TestObjectCount * OptimalParallelSearchStep));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Action GetTestMethod(RoundBenchmarkType benchmarkType) => benchmarkType switch
|
||||||
|
{
|
||||||
|
RoundBenchmarkType.MathFloor => RoundWithMathFloor,
|
||||||
|
RoundBenchmarkType.MathRound => RoundWithMathRound,
|
||||||
|
RoundBenchmarkType.WithTypecasting => RoundWithTypeCasting,
|
||||||
|
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
static class RoundUpToPowerOf2Alternatives
|
||||||
|
{
|
||||||
|
private static readonly int[] _powersOfTwo =
|
||||||
|
{
|
||||||
|
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
|
||||||
|
2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576,
|
||||||
|
2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824
|
||||||
|
};
|
||||||
|
|
||||||
|
public static int BinarySearch(int value)
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Input must be a positive integer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the smallest power of 2 greater than or equal to value using a lookup table
|
||||||
|
int index = Array.BinarySearch(_powersOfTwo, value);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
// If value is not a power of 2, use the next power of 2 from the table
|
||||||
|
index = ~index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _powersOfTwo[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int RightBitShifting(int value)
|
||||||
|
{
|
||||||
|
// Decrease value by 1 to handle the case where the input is already a power of 2
|
||||||
|
value--;
|
||||||
|
|
||||||
|
value |= value >> 1;
|
||||||
|
value |= value >> 2;
|
||||||
|
value |= value >> 4;
|
||||||
|
value |= value >> 8;
|
||||||
|
value |= value >> 16;
|
||||||
|
|
||||||
|
return value + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int LeftBitShifting(int value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure value is a power of 2 or the next power of 2
|
||||||
|
int result = 1;
|
||||||
|
while (result < value)
|
||||||
|
{
|
||||||
|
result = checked(result << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RoundUpToPowerOf2BenchmarkType
|
||||||
|
{
|
||||||
|
Undefined,
|
||||||
|
BitOperations,
|
||||||
|
RightBitShifting,
|
||||||
|
LeftBitShifting,
|
||||||
|
BinarySearch,
|
||||||
|
IsPowOf2,
|
||||||
|
IsPowOf2_GreaterThanFirst,
|
||||||
|
IsPowOf2_WithIf,
|
||||||
|
IsPowOf2_GreaterEqual,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoundUpToPowerOf2vsOtherBenchmarks : BaselineVsActualBenchmarkBase<RoundUpToPowerOf2BenchmarkType>
|
||||||
|
{
|
||||||
|
// [Params(-850_000, 850_000)]
|
||||||
|
[Params(-int.MaxValue, int.MaxValue)]
|
||||||
|
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||||
|
|
||||||
|
[Params(RoundUpToPowerOf2BenchmarkType.IsPowOf2)]
|
||||||
|
public override RoundUpToPowerOf2BenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||||
|
|
||||||
|
[Params(RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterThanFirst, RoundUpToPowerOf2BenchmarkType.IsPowOf2_WithIf, RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterEqual)]
|
||||||
|
// [Params(RoundUpToPowerOf2BenchmarkType.RightBitShifting, RoundUpToPowerOf2BenchmarkType.LeftBitShifting, RoundUpToPowerOf2BenchmarkType.BinarySearch)]
|
||||||
|
public override RoundUpToPowerOf2BenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
private void BitOperations()
|
||||||
|
{
|
||||||
|
DoNothing.With(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)base.TestObjectCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RightBitShifting()
|
||||||
|
{
|
||||||
|
DoNothing.With(RoundUpToPowerOf2Alternatives.RightBitShifting(TestObjectCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LeftBitShifting()
|
||||||
|
{
|
||||||
|
DoNothing.With(RoundUpToPowerOf2Alternatives.LeftBitShifting(TestObjectCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BinarySearch()
|
||||||
|
{
|
||||||
|
DoNothing.With(RoundUpToPowerOf2Alternatives.BinarySearch(TestObjectCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IsPowOf2()
|
||||||
|
{
|
||||||
|
DoNothing.With((TestObjectCount & (TestObjectCount - 1)) == 0 && TestObjectCount > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IsPowOf2_GreaterThanFirst()
|
||||||
|
{
|
||||||
|
DoNothing.With(TestObjectCount > 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IsPowOf2_WithIf()
|
||||||
|
{
|
||||||
|
#pragma warning disable IDE0075 // This is intentional
|
||||||
|
DoNothing.With(TestObjectCount > 0 ? (TestObjectCount & (TestObjectCount - 1)) == 0 : false);
|
||||||
|
#pragma warning restore IDE0075
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IsPowOf2_GreaterEqual()
|
||||||
|
{
|
||||||
|
DoNothing.With(TestObjectCount >= 0 && TestObjectCount != 0 && (TestObjectCount & (TestObjectCount - 1)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Action? GetTestMethod(RoundUpToPowerOf2BenchmarkType benchmarkType) => benchmarkType switch
|
||||||
|
{
|
||||||
|
RoundUpToPowerOf2BenchmarkType.BitOperations => BitOperations,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.RightBitShifting => RightBitShifting,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.LeftBitShifting => LeftBitShifting,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.BinarySearch => BinarySearch,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.IsPowOf2 => IsPowOf2,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterThanFirst => IsPowOf2_GreaterThanFirst,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.IsPowOf2_WithIf => IsPowOf2_WithIf,
|
||||||
|
RoundUpToPowerOf2BenchmarkType.IsPowOf2_GreaterEqual => IsPowOf2_GreaterEqual,
|
||||||
|
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override void PrepareData<T>(T benchmarkType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public enum SpanConstructorVsTypecastingBenchmarkType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Constructor,
|
||||||
|
TypeCasting,
|
||||||
|
}
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class SpanConstructorVsTypecastingBenchmarks : BaselineVsActualBenchmarkBase<SpanConstructorVsTypecastingBenchmarkType>
|
||||||
|
{
|
||||||
|
private int[]? TestData { get; set; }
|
||||||
|
|
||||||
|
[Params(SpanConstructorVsTypecastingBenchmarkType.TypeCasting)]
|
||||||
|
public override SpanConstructorVsTypecastingBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||||
|
|
||||||
|
[Params(SpanConstructorVsTypecastingBenchmarkType.Constructor)]
|
||||||
|
public override SpanConstructorVsTypecastingBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
[Params(8)]
|
||||||
|
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||||
|
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
var benchmark = new SpanConstructorVsTypecastingBenchmarks();
|
||||||
|
benchmark.Setup();
|
||||||
|
benchmark.Constructor();
|
||||||
|
benchmark.TypeCasting();
|
||||||
|
benchmark.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Constructor()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<int> span = new(TestData);
|
||||||
|
DoNothing.With(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TypeCasting()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<int> span = TestData;
|
||||||
|
DoNothing.With(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Setup()
|
||||||
|
{
|
||||||
|
TestData = new int[TestObjectCount];
|
||||||
|
base.Setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Action? GetTestMethod(SpanConstructorVsTypecastingBenchmarkType benchmarkType) => benchmarkType switch
|
||||||
|
{
|
||||||
|
SpanConstructorVsTypecastingBenchmarkType.Constructor => Constructor,
|
||||||
|
SpanConstructorVsTypecastingBenchmarkType.TypeCasting => TypeCasting,
|
||||||
|
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Collections.Benchmarks.Core;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
public enum SpanVsArrayBenchmarkType
|
||||||
|
{
|
||||||
|
ArrayGetWithVar,
|
||||||
|
ArrayGetWithField,
|
||||||
|
SpanGet,
|
||||||
|
ArraySetWithVar,
|
||||||
|
ArraySetWithField,
|
||||||
|
SpanSet
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SpanVsArrayBenchmarks : DataDrivenBenchmarksBase<SpanVsArrayBenchmarkType>
|
||||||
|
{
|
||||||
|
// [Params(SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet)]
|
||||||
|
// [Params(SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet)]
|
||||||
|
[Params
|
||||||
|
(
|
||||||
|
SpanVsArrayBenchmarkType.ArrayGetWithVar, SpanVsArrayBenchmarkType.SpanGet,
|
||||||
|
SpanVsArrayBenchmarkType.ArraySetWithField, SpanVsArrayBenchmarkType.ArraySetWithVar, SpanVsArrayBenchmarkType.SpanSet
|
||||||
|
)]
|
||||||
|
public override SpanVsArrayBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||||
|
|
||||||
|
[Params(SpanVsArrayBenchmarkType.ArrayGetWithField)]
|
||||||
|
// [Params(SpanVsArrayBenchmarkType.ArraySetWithField)]
|
||||||
|
public override SpanVsArrayBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||||
|
|
||||||
|
protected override Action GetTestMethod(SpanVsArrayBenchmarkType benchmarkType) => benchmarkType switch
|
||||||
|
{
|
||||||
|
SpanVsArrayBenchmarkType.ArrayGetWithVar => ArrayGetWithVar,
|
||||||
|
SpanVsArrayBenchmarkType.ArrayGetWithField => ArrayGetWithField,
|
||||||
|
SpanVsArrayBenchmarkType.SpanGet => SpanGet,
|
||||||
|
SpanVsArrayBenchmarkType.ArraySetWithVar => ArraySetWithVar,
|
||||||
|
SpanVsArrayBenchmarkType.ArraySetWithField => ArraySetWithField,
|
||||||
|
SpanVsArrayBenchmarkType.SpanSet => SpanSet,
|
||||||
|
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||||
|
};
|
||||||
|
|
||||||
|
public void ArrayGetWithVar()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ArrayGetWithField()
|
||||||
|
{
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(_testObjects![i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SpanGet()
|
||||||
|
{
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
Span<int> data = new(_testObjects, 0, dataCount);
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
DoNothing.With(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ArraySetWithVar()
|
||||||
|
{
|
||||||
|
var data = TestObjects;
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ArraySetWithField()
|
||||||
|
{
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
_testObjects![i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SpanSet()
|
||||||
|
{
|
||||||
|
var dataCount = TestObjectCount;
|
||||||
|
Span<int> data = new(_testObjects, 0, dataCount);
|
||||||
|
for (int i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,59 @@
|
|||||||
|
// Ignore Spelling: Poc
|
||||||
|
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks.POC
|
||||||
|
{
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class TaskRunVsTaskFactoryStartNewBenchmarks
|
||||||
|
{
|
||||||
|
public int NumberOfTasks = 100;
|
||||||
|
private static readonly TaskFactory _taskPool = new();
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void OwnTaskFactory()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < NumberOfTasks; i++)
|
||||||
|
{
|
||||||
|
_ = _taskPool.StartNew(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskRun()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < NumberOfTasks; i++)
|
||||||
|
{
|
||||||
|
_ = Task.Run(() => { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public void TaskFactoryStartNew()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < NumberOfTasks; i++)
|
||||||
|
{
|
||||||
|
_ = Task.Factory.StartNew(() => { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskConstructor()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < NumberOfTasks; i++)
|
||||||
|
{
|
||||||
|
new Task(() => { }).Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void TaskConstructorWithKnownScheduler()
|
||||||
|
{
|
||||||
|
TaskScheduler scheduler = TaskScheduler.Current;
|
||||||
|
for (var i = 0; i < NumberOfTasks; i++)
|
||||||
|
{
|
||||||
|
new Task(() => { }).Start(scheduler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
|
||||||
|
#pragma warning disable RCS1036, RCS1213, IDE0051
|
||||||
|
|
||||||
|
namespace Recyclable.Collections.Benchmarks
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
static IConfig BenchmarkConfig { get; } = ManualConfig.Create(DefaultConfig.Instance)
|
||||||
|
.WithOptions(ConfigOptions.DisableOptimizationsValidator | ConfigOptions.JoinSummary);
|
||||||
|
|
||||||
|
static void RunAssemblyBenchmarks()
|
||||||
|
{
|
||||||
|
_ = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(new[] { "-f*" });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RunRecyclableCollectionsBenchmarks()
|
||||||
|
{
|
||||||
|
_ = BenchmarkRunner.Run<RecyclableCollectionsBenchmarks>(BenchmarkConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RunSelectedBenchmarks()
|
||||||
|
{
|
||||||
|
// ****************
|
||||||
|
// *** Template ***
|
||||||
|
// ****************
|
||||||
|
var benchmark = new RecyclableCollectionsBenchmarks();
|
||||||
|
benchmark.Setup();
|
||||||
|
|
||||||
|
foreach (var _ in Enumerable.Range(1, 1000))
|
||||||
|
{
|
||||||
|
//benchmark.RecyclableList_Create_WithCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmark.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RunPocBenchmarks()
|
||||||
|
{
|
||||||
|
//_ = BenchmarkRunner.Run<BoolOrCompareBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<DelegateVsComparerBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<ModuloBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<RefVsInstanceMemberBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<SpanVsArrayBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<LessOperatorVsAndOperatorBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<EqualVsContainsInConsecutiveOrderBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<RoundUpToPowerOf2vsOtherBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<GreaterOperatorVsNotEqualOperatorBenchmarks>(BenchmarkConfig);
|
||||||
|
//_ = BenchmarkRunner.Run<SpanConstructorVsTypecastingBenchmarks>(BenchmarkConfig);
|
||||||
|
|
||||||
|
//ArraySizeLimitBenchmarks.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
// RunRecyclableCollectionsBenchmarks();
|
||||||
|
RunPocBenchmarks();
|
||||||
|
// RunSelectedBenchmarks();
|
||||||
|
// RunAssemblyBenchmarks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"WSL": {
|
||||||
|
"commandName": "WSL2",
|
||||||
|
"distributionName": ""
|
||||||
|
},
|
||||||
|
".Net": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"nativeDebugging": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
|
<StartupObject>Recyclable.Collections.Benchmarks.Program</StartupObject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Collections.Benchmarks.Core" Version="0.0.4" />
|
||||||
|
<PackageReference Include="Collections.Pooled" Version="1.0.82" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Recyclable.CollectionsTests\Recyclable.CollectionsTests.csproj" />
|
||||||
|
<ProjectReference Include="..\Recyclable.Collections\Recyclable.Collections.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0|AnyCPU'">
|
||||||
|
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ActiveDebugProfile>.Net</ActiveDebugProfile>
|
||||||
|
<ActiveDebugFramework>net7.0</ActiveDebugFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user