Skip to content

Commit 8a9f562

Browse files
committed
initial version
1 parent 536fae0 commit 8a9f562

File tree

12 files changed

+593
-0
lines changed

12 files changed

+593
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.vs/
2+
*bin/
3+
*obj/
4+
*.user

PatternScanBench.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.28803.156
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PatternScanBench", "PatternScanBench\PatternScanBench.csproj", "{298D7747-9F1C-4BCC-84F6-4EAB411B6183}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|x64 = Debug|x64
11+
Release|x64 = Release|x64
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{298D7747-9F1C-4BCC-84F6-4EAB411B6183}.Debug|x64.ActiveCfg = Debug|x64
15+
{298D7747-9F1C-4BCC-84F6-4EAB411B6183}.Debug|x64.Build.0 = Debug|x64
16+
{298D7747-9F1C-4BCC-84F6-4EAB411B6183}.Release|x64.ActiveCfg = Release|x64
17+
{298D7747-9F1C-4BCC-84F6-4EAB411B6183}.Release|x64.Build.0 = Release|x64
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {B31FA5B6-1921-41DB-B9C5-52A05C1C8844}
24+
EndGlobalSection
25+
EndGlobal

PatternScanBench/App.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
5+
</startup>
6+
</configuration>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+

2+
namespace PatternScanBench.Implementations
3+
{
4+
/// <summary>
5+
/// Pattern scan implementation 'BoyerMooreHorspool' - by DarthTon (ported to C# by uberhalit)
6+
/// https://github.com/DarthTon
7+
/// https://github.com/learn-more/findpattern-bench/blob/master/patterns/DarthTon.h
8+
///
9+
/// Boyer-Moore-Horspool with wildcards implementation
10+
/// </summary>
11+
internal class PatternScanBoyerMooreHorspool : PatternScanAlgorithm
12+
{
13+
internal override string Creator => "DarthTon";
14+
internal PatternScanBoyerMooreHorspool() { }
15+
16+
private const byte wildcard = 0xCC;
17+
private static uint[] FillShiftTable(byte[] pPattern)
18+
{
19+
uint idx = 0;
20+
uint last = (uint)pPattern.Length - 1;
21+
22+
// Get last wildcard position
23+
for (idx = last; idx > 0 && pPattern[idx] != wildcard; --idx) { }
24+
uint diff = last - idx;
25+
if (diff == 0)
26+
diff = 1;
27+
28+
// Prepare shift table
29+
uint[] badCharSkip = new uint[256];
30+
for (idx = 0; idx <= 255; ++idx)
31+
badCharSkip[idx] = diff;
32+
for (idx = last - diff; idx < last; ++idx)
33+
badCharSkip[pPattern[idx]] = last - idx;
34+
return badCharSkip;
35+
}
36+
37+
/// <summary>
38+
/// Initializes a new 'PatternScanBoyerMooreHorspool'.
39+
/// </summary>
40+
/// <param name="cbMemory">The byte array to scan.</param>
41+
/// <returns>An optional string to display next to benchmark results.</returns>
42+
internal override string Init(in byte[] cbMemory)
43+
{
44+
return "";
45+
}
46+
47+
/// <summary>
48+
/// Returns address of pattern using 'BoyerMooreHorspool' implementation by DarthTon. Can match 0.
49+
/// </summary>
50+
/// <param name="cbMemory">The byte array to scan.</param>
51+
/// <param name="cbPattern">The byte pattern to look for, wildcard positions are replaced by 0.</param>
52+
/// <param name="szMask">A string that determines how pattern should be matched, 'x' is match, '?' acts as wildcard.</param>
53+
/// <returns></returns>
54+
internal override long FindPattern(in byte[] cbMemory, in byte[] cbPattern, string szMask)
55+
{
56+
int scanEnd = cbMemory.Length - cbPattern.Length;
57+
int last = cbPattern.Length - 1;
58+
59+
byte[] newPattern = GenerateWildcardPattern(cbPattern, szMask);
60+
uint[] badCharSkip = FillShiftTable(newPattern);
61+
62+
// Search
63+
uint pScanPos = 0;
64+
for (; pScanPos <= scanEnd; pScanPos += badCharSkip[cbMemory[pScanPos + last]])
65+
{
66+
for (int idx = last; idx >= 0; --idx)
67+
{
68+
if (newPattern[idx] != wildcard && cbMemory[idx + pScanPos] != newPattern[idx])
69+
break;
70+
if (idx == 0)
71+
return pScanPos;
72+
}
73+
}
74+
return -1;
75+
}
76+
77+
private byte[] GenerateWildcardPattern(byte[] cbPattern, string szMask)
78+
{
79+
byte[] newPattern = new byte[cbPattern.Length];
80+
for (int i = 0; i < szMask.Length; i++)
81+
{
82+
if (szMask[i] != 'x') newPattern[i] = wildcard;
83+
else newPattern[i] = cbPattern[i];
84+
}
85+
86+
return newPattern;
87+
}
88+
}
89+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+

2+
namespace PatternScanBench.Implementations
3+
{
4+
/// <summary>
5+
/// Pattern scan implementation 'NaiveFor' - by uberhalit
6+
/// https://github.com/uberhalit
7+
/// </summary>
8+
internal class PatternScanNaiveFor : PatternScanAlgorithm
9+
{
10+
/// <summary>
11+
/// Authors name.
12+
/// </summary>
13+
internal override string Creator => "uberhalit";
14+
15+
internal PatternScanNaiveFor() { }
16+
17+
/// <summary>
18+
/// Initializes a new 'PatternScanNaiveFor'.
19+
/// </summary>
20+
/// <param name="cbMemory">The byte array to scan.</param>
21+
/// <returns>An optional string to display next to benchmark results.</returns>
22+
internal override string Init(in byte[] cbMemory)
23+
{
24+
return "";
25+
}
26+
27+
/// <summary>
28+
/// Returns address of pattern using 'NaiveFor' implementation by uberhalit. Can match 0.
29+
/// </summary>
30+
/// <param name="cbMemory">The byte array to scan.</param>
31+
/// <param name="cbPattern">The byte pattern to look for, wildcard positions are replaced by 0.</param>
32+
/// <param name="szMask">A string that determines how pattern should be matched, 'x' is match, '?' acts as wildcard.</param>
33+
/// <returns></returns>
34+
internal override long FindPattern(in byte[] cbMemory, in byte[] cbPattern, string szMask)
35+
{
36+
long ix;
37+
int iy;
38+
bool bFound = false;
39+
int patternLength = cbPattern.Length;
40+
int dataLength = cbMemory.Length - patternLength;
41+
42+
for (ix = 0; ix < dataLength; ix++)
43+
{
44+
bFound = true;
45+
for (iy = 0; iy < patternLength; iy++)
46+
{
47+
if (szMask[iy] != 'x' || cbPattern[iy] == cbMemory[ix + iy])
48+
continue;
49+
bFound = false;
50+
break;
51+
}
52+
53+
if (bFound)
54+
return ix;
55+
}
56+
57+
return -1;
58+
}
59+
}
60+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Linq;
2+
3+
namespace PatternScanBench.Implementations
4+
{
5+
/// <summary>
6+
/// Pattern scan implementation 'NaiveLINQ' - by lolp1
7+
/// https://github.com/lolp1
8+
/// </summary>
9+
internal class PatternScanNaiveLINQ : PatternScanAlgorithm
10+
{
11+
internal override string Creator => "lolp1";
12+
internal PatternScanNaiveLINQ() { }
13+
14+
/// <summary>
15+
/// Initializes a new 'PatternScanNaiveLINQ'.
16+
/// </summary>
17+
/// <param name="cbMemory">The byte array to scan.</param>
18+
/// <returns>An optional string to display next to benchmark results.</returns>
19+
internal override string Init(in byte[] cbMemory)
20+
{
21+
return "";
22+
}
23+
24+
/// <summary>
25+
/// Returns address of pattern using 'NaiveLINQ' implementation by lolp1. Can match 0.
26+
/// </summary>
27+
/// <param name="cbMemory">The byte array to scan.</param>
28+
/// <param name="cbPattern">The byte pattern to look for, wildcard positions are replaced by 0.</param>
29+
/// <param name="szMask">A string that determines how pattern should be matched, 'x' is match, '?' acts as wildcard.</param>
30+
/// <returns></returns>
31+
internal override long FindPattern(in byte[] cbMemory, in byte[] cbPattern, string szMask)
32+
{
33+
byte[] pattern = cbPattern;
34+
byte[] patternData = cbMemory;
35+
36+
long patternDataLength = patternData.Length;
37+
for (var offset = 0; offset < patternDataLength; offset++)
38+
{
39+
if (szMask.Where((m, b) => m == 'x' && pattern[b] != patternData[b + offset]).Any())
40+
continue;
41+
42+
return offset;
43+
}
44+
return -1;
45+
}
46+
}
47+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+

2+
namespace PatternScanBench.Implementations
3+
{
4+
/**
5+
1. Copy this class and replace 'Template' in its name with your implementation name
6+
2. Replace all 'Template' with your implementation name
7+
3. Replace all 'author' with your name
8+
4. If your implementation needs some initialization done add it to Init()
9+
5. Write your implementation into FindPattern(), must be able to match zeros too
10+
6. Remove all multi line comment blocks including this one
11+
* NO DLLs/libraries
12+
* NO assembly references outside of default .NET 4.6
13+
* NO changes to build process
14+
* NO unsafe code
15+
* has to work on 64 bit Windows 10 1709 and newer
16+
* has to work on **most** modern AMD64 processors
17+
*/
18+
/// <summary>
19+
/// Pattern scan implementation 'Template' - by author
20+
/// </summary>
21+
internal class PatternScanTemplate : PatternScanAlgorithm
22+
{
23+
internal override string Creator => "author";
24+
internal PatternScanTemplate() { }
25+
26+
/// <summary>
27+
/// Initializes a new 'PatternScanTemplate'.
28+
/// </summary>
29+
/// <param name="cbMemory">The byte array to scan.</param>
30+
/// <returns>An optional string to display next to benchmark results.</returns>
31+
internal override string Init(in byte[] cbMemory)
32+
{
33+
/**
34+
* Do whatever you need here
35+
* This won't be benchmarked
36+
*/
37+
return "";
38+
}
39+
40+
/// <summary>
41+
/// Returns address of pattern using 'Template' implementation by author. Can match 0.
42+
/// </summary>
43+
/// <param name="cbMemory">The byte array to scan.</param>
44+
/// <param name="cbPattern">The byte pattern to look for, wildcard positions are replaced by 0.</param>
45+
/// <param name="szMask">A string that determines how pattern should be matched, 'x' is match, '?' acts as wildcard.</param>
46+
/// <returns></returns>
47+
internal override long FindPattern(in byte[] cbMemory, in byte[] cbPattern, string szMask)
48+
{
49+
/**
50+
Add your implementation here
51+
Whole function will be benchmarked
52+
*/
53+
return -1;
54+
}
55+
}
56+
}
48.3 MB
Binary file not shown.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{298D7747-9F1C-4BCC-84F6-4EAB411B6183}</ProjectGuid>
8+
<OutputType>Exe</OutputType>
9+
<RootNamespace>PatternScanBench</RootNamespace>
10+
<AssemblyName>PatternScanBench</AssemblyName>
11+
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
12+
<FileAlignment>512</FileAlignment>
13+
<Deterministic>true</Deterministic>
14+
<TargetFrameworkProfile />
15+
</PropertyGroup>
16+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
17+
<DebugSymbols>true</DebugSymbols>
18+
<OutputPath>bin\x64\Debug\</OutputPath>
19+
<DefineConstants>DEBUG;TRACE</DefineConstants>
20+
<DebugType>full</DebugType>
21+
<PlatformTarget>x64</PlatformTarget>
22+
<ErrorReport>prompt</ErrorReport>
23+
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
24+
<Prefer32Bit>true</Prefer32Bit>
25+
</PropertyGroup>
26+
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
27+
<OutputPath>bin\x64\Release\</OutputPath>
28+
<DefineConstants>TRACE</DefineConstants>
29+
<Optimize>true</Optimize>
30+
<DebugType>pdbonly</DebugType>
31+
<PlatformTarget>x64</PlatformTarget>
32+
<ErrorReport>prompt</ErrorReport>
33+
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
34+
<Prefer32Bit>true</Prefer32Bit>
35+
</PropertyGroup>
36+
<PropertyGroup />
37+
<ItemGroup>
38+
<Reference Include="System" />
39+
<Reference Include="System.Core" />
40+
<Reference Include="System.Xml.Linq" />
41+
<Reference Include="System.Data.DataSetExtensions" />
42+
<Reference Include="Microsoft.CSharp" />
43+
<Reference Include="System.Data" />
44+
<Reference Include="System.Net.Http" />
45+
<Reference Include="System.Xml" />
46+
</ItemGroup>
47+
<ItemGroup>
48+
<Compile Include="Implementations\PatternScanNaiveFor.cs" />
49+
<Compile Include="Implementations\PatternScanNaiveLINQ.cs" />
50+
<Compile Include="Implementations\PatternScanBoyerMooreHorspool.cs" />
51+
<Compile Include="Implementations\PatternScanTemplate.cs" />
52+
<Compile Include="Program.cs" />
53+
<Compile Include="Properties\AssemblyInfo.cs" />
54+
</ItemGroup>
55+
<ItemGroup>
56+
<None Include="App.config" />
57+
</ItemGroup>
58+
<ItemGroup>
59+
<Folder Include="Memorydump\" />
60+
</ItemGroup>
61+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
62+
</Project>

0 commit comments

Comments
 (0)