JAVA PROGRAMMING
String Processing: Effective method to check string contains in Java
There are many applications (e.g. information retrieval, Natural Language processing) that require
searching a large string for words, terms, or statements. The link below describe several methods to
do that using C#.
In this assignment, you are expected to use a large input text file (of more than 3000 words). You will
evaluate 3 different method, based on performance. All three methods should have the same
signature
Public int NumberOfOccurrences (string inputfile, string word)
The output will be the number of time the word occur in the input file. Evaluate the three methods
you selected based on performance. Test your code with 5 different test cases.
http://cc.davelozinski.com/c-sharp/fastest-way-to-check-if-a-string-occurs-within-a-string
C# .NET: FASTEST WAY TO CHECK IF A
STRING OCCURS WITHIN A STRING AUGUST 17, 2013 DAVID LOZINSKI 12 COMMENTS
2
Using C# .Net: Fastest Way to check if a string occurs within
a string.
This will examine many techniques to determine in C# .Net: Fastest Way to check if a string
occurs within a string.
The Background:
How many of us C# programmers have had to check if a string is contained within another
string? A simple match. We don’t care how many times it may exist, we only want to know if it
does.
There are numerous native C# methods for doing this: String.Contains(), String.IndexOf(),
through Regex regular expressions, and similar options for those programmers obsessed with
LINQ.
So that’s when this curious consultant started wondering… what is the fastest way to test and see
if a string is contained within another string?
The Set Up:
I wrote a C# Console application to test 16 different search techniques: 8 single threaded loop; 8
multi-threaded parallel.for loop.
The code is written in Visual Studio 2012 targeting .Net Framework version 4.5 x64. The source
code is available at the end of this blog so you can benchmark it on your own system if you wish.
In a nutshell, the code does the following:
1) Creates an array of random strings that will serve as the strings to be searched using the
System.Web.Security.Membership.GeneratePassword method. We’ll call these “A”.
2) Creates an array of random strings that will serve as the strings being searched for using
the System.Web.Security.Membership.GeneratePassword method. We’ll call these “B”.
3) Executes the techniques to see if any of the search strings occur in the strings to be
searched. The techniques are as follows:
# Technique Code Snippet
T1 A common counting method
for (int x = 0; x < ss.Length; x++)
for (int y = 0; y < sf.Length; y++
c[y] += ((ss[x].Length - ss[x].Replace(sf[y],
String.Empty).Length) / sf[y].Length > 0 ? 1 : 0);
T2
splitting each string in A by
string B and counting the
results.
for (int x = 0; x < ss.Length; x++)
for (int y = 0; y < sf.Length; y++)
c[y] += (ss[x].Split(new string[] { sf[y] },
StringSplitOptions.None).Count() - 1 > 0 ? 1 : 0);
T3
C#’s String.Contains() method.
for (int x = 0; x < ss.Length; x++)
for (int y = 0; y < sf.Length; y++)
c[y] += (ss[x].Contains(sf[y]) == true ? 1 : 0);
T4 C#’s String.IndexOf() method
for (int x = 0; x < ss.Length; x++)
for (int y = 0; y < sf.Length; y++)
c[y] += (ss[x].IndexOf(sf[y]) >= 0 ? 1 : 0);
T5
Using Contains() on a LINQ
query
for (int y = 0; y < sf.Length; y++)
c[y] += ss.Where(o => o.Contains(sf[y])).Count();
T6
Using IndexOf() on a LINQ
query
for (int y = 0; y < sf.Length; y++)
c[y] += ss.Where(o => o.IndexOf(sf[y]) > -1).Count();
T7 C#’s Regex.IsMatch() method
for (int x = 0; x < ss.Length; x++)
for (int y = 0; y < sf.Length; y++)
c[y] += Regex.IsMatch(ss[x], Regex.Escape(sf[y])) == true ? 1 :
0;
T8 AsParallel() with Regex
for (int x = 0; x < ss.Length; x++)
total += sf.AsParallel().Sum(s => Regex.IsMatch(ss[x],
Regex.Escape(s)) ? 1 : 0);
T9
T1 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
subtotal += ((ss[x].Length - ss[x].Replace(sf[y],
String.Empty).Length) / sf[y].Length > 0 ? 1 : 0);
return subtotal;
},
.....
);
T10
T2 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
subtotal += (ss[x].Split(new string[] { sf[y] },
StringSplitOptions.None).Count() - 1 > 0 ? 1 : 0);
return subtotal;
},
.....
);
T11
T3 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
subtotal += (ss[x].Contains(sf[y]) == true ? 1 : 0);
return subtotal;
},
.....
);
T12
T4 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
subtotal += (ss[x].IndexOf(sf[y]) >= 0 ? 1 : 0);
return subtotal;
},
.....
);
T13
T5 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
subtotal += ss.Where(o => o.Contains(sf[x])).Count();
return subtotal;
},
.....
);
T14
T6 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
subtotal += ss.Where(o => o.IndexOf(sf[x]) > -1).Count();
return subtotal;
},
.....
);
T15
T7 implemented with a
Parallel.For construct Parallel.For( .....
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
subtotal += Regex.IsMatch(ss[x], Regex.Escape(sf[y]))
== true ? 1 : 0;
return subtotal;
},
.....
);
T16
T8 implemented with a
Parallel.For construct
Parallel.For( .....
(x, loopState, subtotal) =>
{
subtotal += sf.AsParallel().Sum(s => Regex.IsMatch(ss[x],
Regex.Escape(s)) ? 1 : 0);
return subtotal;
},
.....
);
4) The sum from adding up the number of times a match is found is displayed along with the
execution time
5) The arrays are cleared out and deleted being the responsible programmer I am.
The code assumes all tests will happen with no exception testing because I’m just wanting to test
the raw speed of finding a string in a string. There may be other techniques, but I think these are
the most common. However, if you have a great alternative solution, please post!
The exe file was installed and run on an Alienware M17X R3 running Windows 7 64-bit with 16
GB memory on an i7-2820QM processor.
The test was run for each technique over the following number of comparisons:
Searching for 1 string in 5,000, 25,000, 100,000, and 1,000,000 million strings.
Searching for 100 strings in 5,000, 25,000, 100,000, and 1,000,000 million strings.
Searching for 1000 strings in 5,000, 25,000, 100,000, and 1,000,000 million strings.
In regards to the last two bullet points, I do realize though that in most cases, programmers are
only going to test if 1 or 2 strings occur in another string. But:
1) We’re having fun aren’t we?
2) Why not?
Off To The Races!
Before starting, my hypothesis was that I expected the custom counting method to be the winner
in both the single and multi-threaded groups since it generally does perform the best whether
counting substring occurrences in strings or characters in strings. It’s amazing how fast and
versatile this method is.
All times are indicated in hours:minutes:seconds.milliseconds format. Yes, some took over an
hour! The lower the number, the faster the technique performed.
Green cells indicate the winner(s) for that run.
Yellow cells indicate the second runner(s) up.
Searching for 1 string in each of
5,000 25,000 100,000 1,000,000
T1: Common Counting 0.00 0.00 0.0100000 0.0690040
T2: Count Split String 0.00 0.01 0.0300001 0.2390137
T3: String.Contains() 0.00 0.00 0.0100000 0.1190068
T4: String.IndexOf() 0.00 0.00 0.0200000 0.1220070
T5: Linq.Contains() 0.00 0.00 0.0100000 0.0880050
T6: Linq.IndexOf() 0.00 0.0100001 0.0100001 0.1200069
T7: Regex.IsMatch() 0.01 0.01 0.0500000 0.5340306
T8: AsParallel() with Regex 0.1090063 0.5928010 2.4271172 28.0040902
T9: T1 using Parallel.For 0.04 0.00 0.00 0.0220012
T10: T2 using Parallel.For 0.00 0.01 0.0100000 0.0770044
T11: T3 using Parallel.For 0.00 0.00 0.0100001 0.0240014
T12: T4 using Parallel.For 0.00 0.00 0.00 0.0340019
T13: T5 using Parallel.For 0.00 0.00 0.0100000 0.0920053
T14: T6 using Parallel.For 0.00 0.00 0.0100000 0.1210069
T15: T7 using Parallel.For 0.00 0.02 0.0600001 0.5930339
T16: T8 using Parallel.For 9.5066852 0.9984017 4.1209639 02:40.4553675
Searching for 100 strings in each of
5,000 25,000 100,000 1,000,000
T1: Common Counting 0.0310018 00.1500003 00.6110350 00:05.9901200
T2: Count Split String 0.0890051 00.4200005 01.7090514 00:17.0874199
T3: String.Contains() 0.0400023 00.2000003 00.7900011 00:08.0801731
T4: String.IndexOf() 0.0580033 00.2800004 01.1000016 00:11.1742954
T5: Linq.Contains() 0.0400023 00.2000003 00.8000011 00:08.3932904
T6: Linq.IndexOf() 0.0560032 00.2700004 01.1200016 00:11.4832952
T7: Regex.IsMatch() 1.9920827 10.0042932 39.9819828 06:18.0251803
T8: AsParallel() with Regex 2.6716222 13.2043531 47.6943911 07:51.0616836
T9: T1 using Parallel.For 0.0100000 0.0300000 00.1320076 00:01.3670726
T10: T2 using Parallel.For 0.0400001 0.1700014 00.9670553 00:08.1112882
T11: T3 using Parallel.For 0.0100000 0.0610007 00.2090119 00:02.1291190
T12: T4 using Parallel.For 0.0100000 0.0720041 00.2890166 00:02.9511688
T13: T5 using Parallel.For 0.0100000 0.0580033 00.2230127 00:02.4241386
T14: T6 using Parallel.For 0.0200000 0.0830025 00.3260187 00:03.3881732
T15: T7 using Parallel.For 1.5900023 7.9991942 56.9313084 13:04.8093665
T16: T8 using Parallel.For 1:28.8255242 7:37.3664312 35.9700924 06:47.5672122
Searching for 1,000 strings in each of
5,000 25,000 100,000 1,000,000
T1: Common Counting 00.3400005 0:01.4500020 0:05.8460253 0:00:58.7804783
T2: Count Split String 00.9260396 0:04.1800059 0:16.9595644 0:02:48.1291422
T3: String.Contains() 00.4140236 0:02.0341091 0:08.0100821 0:01:20.2320263
T4: String.IndexOf() 00.5780331 0:02.8061605 0:11.0782430 0:01:51.8527094
T5: Linq.Contains() 00.4080233 0:01.9950192 0:08.1842706 0:01:23.5070696
T6: Linq.IndexOf() 00.5830334 0:02.7400039 0:11.2912949 0:01:54.8588055
T7: Regex.IsMatch() 20.3724376 1:40.5314815 6:28.7074927 1:06:19.6771386
T8: AsParallel() with Regex 16.1745050 1:21.2604800 5:29.5454050 0:56:01.1048914
T9: T1 using Parallel.For 00.0770011 0:00.3400194 0:01.3430768 0:00:13.4787570
T10: T2 using Parallel.For 00.3550013 0:01.7851021 0:06.7901925 0:01:12.7307796
T11: T3 using Parallel.For 00.1160039 0:00.5270302 0:02.1261188 0:00:23.4993413
T12: T4 using Parallel.For 00.1510086 0:00.7440425 0:02.9851708 0:00:33.0888926
T13: T5 using Parallel.For 00.1140065 0:00.5470291 0:02.2521288 0:00:25.5383988
T14: T6 using Parallel.For 00.1560067 0:00.7890429 0:03.1391778 0:00:35.0009991
T15: T7 using Parallel.For 18.2395857 2:57.7773771 6:24.3384817 1:45:56.4084164
T16: T8 using Parallel.For 14.9139029 1:15.3743422 4:58.9888284 0:52:50.3983364
The Results:
It’s quite obvious technique T1 implementing a common counting method won by running
faster every single time than any of the native C# methods, Linq queries, or Regex matching. As
the old saying goes, “green across the board”.
To my surprise, String.Contains() consistently ran second fastest, and stood out from the rest of
the pack of contenders as we increased the number of strings we were searching for.
I’m also surprised the String.IndexOf() ran so slow in comparison. Definitely a method to avoid
using except when necessary.
The Linq.Contains() technique isn’t a bad alternative to using String.Contains(). Personally, I’m
not crazy about Linq and avoid it like the plague, but I have to give it a fair assessment in these
tests.
Regex is a powerful tool, but as one can see from the results, if you know you’re going to
perform checks 100 times or more for a simple string rather than a complicated pattern, Regex
should not be used.
In Summary:
On my system, unless someone spots a flaw in my test code, Technique 1 with the common
counting method was the winner. Any application that needs micro optimization or where speed
is of the essence, nothing else should be considered. You just need to decide when to use the
single-threaded or multi-threaded technique depending on your application’s requirements.
Here’s the basis of that code. If it returns a value > 0, the substring was found:
return (strToSearch.Length - strToSearch.Replace(strKeyToLookFor,
String.Empty).Length) / strKeyToLookFor.Length;
Otherwise, if you don’t mind code running ever so slightly slower and want easy code
readability, C#’s native String.Contains() method is the way to go. It’s a simple, elegant, one-
liner, and performs relatively well in both single and multi-threaded renditions.
Unless you need the actual starting index in the string where the match is found, then when it
comes to speed, everything else shouldn’t be considered.
The Code: using System;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
namespace TestApplication
{
class Program
{
static void Main(string[] args)
{
DateTime end;
DateTime start = DateTime.Now;
Console.WriteLine("### Overall Start Time: " + start.ToLongTimeString());
Console.WriteLine();
TestFastestWayToSeeIfAStringOccursInAString(5000, 1);
TestFastestWayToSeeIfAStringOccursInAString(25000, 1);
TestFastestWayToSeeIfAStringOccursInAString(100000, 1);
TestFastestWayToSeeIfAStringOccursInAString(1000000, 1);
TestFastestWayToSeeIfAStringOccursInAString(5000, 100);
TestFastestWayToSeeIfAStringOccursInAString(25000, 100);
TestFastestWayToSeeIfAStringOccursInAString(100000, 100);
TestFastestWayToSeeIfAStringOccursInAString(1000000, 100);
TestFastestWayToSeeIfAStringOccursInAString(5000, 1000);
TestFastestWayToSeeIfAStringOccursInAString(25000, 1000);
TestFastestWayToSeeIfAStringOccursInAString(100000, 1000);
TestFastestWayToSeeIfAStringOccursInAString(1000000, 1000);
end = DateTime.Now;
Console.WriteLine();
Console.WriteLine("### Overall End Time: " + end.ToLongTimeString());
Console.WriteLine("### Overall Run Time: " + (end - start));
Console.WriteLine();
Console.WriteLine("Hit Enter to Exit");
Console.ReadLine();
}
//###############################################################
//what is the fastest way to see if a string occurs in a string?
static void TestFastestWayToSeeIfAStringOccursInAString(int NumberOfStringsToGenerate,
int NumberOfSearchCharsToGenerate)
{
Console.WriteLine("######## " +
System.Reflection.MethodBase.GetCurrentMethod().Name);
Console.WriteLine("Number of Random Strings that will be generated: " +
NumberOfStringsToGenerate.ToString("#,##0"));
Console.WriteLine("Number of Search Strings that will be generated: " +
NumberOfSearchCharsToGenerate.ToString("#,##0"));
Console.WriteLine();
object lockObject = new object();
int total = 0;
DateTime end = DateTime.Now;
DateTime start = DateTime.Now;
//the strings to search
string[] ss = new string[NumberOfStringsToGenerate];
//the chars/strings to look for. We use both because we're testing some string
methods too.
string[] sf = new string[NumberOfSearchCharsToGenerate];
//the count of each substring finding
int[] c = new int[sf.Length];
//Generate the string arrays
int z = 10;
//yes I realize that most real world applications people are going to search strings
//that are "human readable" and not random like I generate below. But this is a test
//and I'm not about to type of millions of different strings for testing.
//strings to be searched. Completely random. Using generate password method to come
up with all sorts of mixtures.
Console.WriteLine("Generating strings to search.");
for (int x = 0; x < ss.Length; x++)
{
ss[x] = System.Web.Security.Membership.GeneratePassword(z, x % 5);
z += 1;
if (z > 25)
z = 10;
}
//strings to search for
Console.WriteLine("Generating strings to search for.");
z = 2;
for (int x = 0; x < sf.Length; x++)
{
sf[x] = System.Web.Security.Membership.GeneratePassword(z, x % 2);
z += 1;
if (z > 8)
z = 2;
}
Console.WriteLine("###########################################################");
Console.WriteLine();
//return (strToSearch.Length - strToSearch.Replace(strKeyToLookFor,
String.Empty).Length) / strKeyToLookFor.Length;
Console.WriteLine("Starting method: "custom string method" ");
start = DateTime.Now;
for (int x = 0; x < ss.Length; x++)
{
for (int y = 0; y < sf.Length; y++)
{
c[y] += ((ss[x].Length - ss[x].Replace(sf[y], String.Empty).Length) /
sf[y].Length > 0 ? 1 : 0);
}
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(c, 0, c.Length);
Console.WriteLine("Starting method: "count split string on string" ");
start = DateTime.Now;
for (int x = 0; x < ss.Length; x++)
{
for (int y = 0; y < sf.Length; y++)
{
c[y] += (ss[x].Split(new string[] { sf[y] }, StringSplitOptions.None).Count()
- 1 > 0 ? 1 : 0);
}
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(c, 0, c.Length);
Console.WriteLine("Starting method: "String.Contains" ");
start = DateTime.Now;
for (int x = 0; x < ss.Length; x++)
{
for (int y = 0; y < sf.Length; y++)
{
c[y] += (ss[x].Contains(sf[y]) == true ? 1 : 0);
}
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(c, 0, c.Length);
Console.WriteLine("Starting method: "String.indexOf" ");
start = DateTime.Now;
for (int x = 0; x < ss.Length; x++)
{
for (int y = 0; y < sf.Length; y++)
{
c[y] += (ss[x].IndexOf(sf[y]) >= 0 ? 1 : 0);
}
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(c, 0, c.Length);
Console.WriteLine("Starting method: "linq contains usage" ");
start = DateTime.Now;
for (int y = 0; y < sf.Length; y++)
{
c[y] += ss.Where(o => o.Contains(sf[y])).Count();
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(c, 0, c.Length);
Console.WriteLine("Starting method: "linq with IndexOf usage" ");
start = DateTime.Now;
for (int y = 0; y < sf.Length; y++)
{
c[y] += ss.Where(o => o.IndexOf(sf[y]) > -1).Count();
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(c, 0, c.Length);
Console.WriteLine("Starting method: "Regex IsMatch uncompiled" ");
start = DateTime.Now;
for (int x = 0; x < ss.Length; x++)
{
for (int y = 0; y < sf.Length; y++)
{
c[y] += Regex.IsMatch(ss[x], Regex.Escape(sf[y])) == true ? 1 : 0;
}
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
total = 0;
for (int x = 0; x < c.Length; x++)
{
total += c[x];
}
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Single AsParallel() Regex" ");
start = DateTime.Now;
for (int x = 0; x < ss.Length; x++)
{
total += sf.AsParallel().Sum(s => Regex.IsMatch(ss[x], Regex.Escape(s)) ? 1 :
0);
}
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For Custom Counting" ");
start = DateTime.Now;
Parallel.For(0, ss.Length,
() => 0,
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
{
subtotal += ((ss[x].Length - ss[x].Replace(sf[y], String.Empty).Length) /
sf[y].Length > 0 ? 1 : 0);
}
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For Split String" ");
start = DateTime.Now;
Parallel.For(0, ss.Length,
() => 0,
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
{
subtotal += (ss[x].Split(new string[] { sf[y] },
StringSplitOptions.None).Count() - 1 > 0 ? 1 : 0);
}
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For String.Contains()" ");
start = DateTime.Now;
Parallel.For(0, ss.Length,
() => 0,
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
{
subtotal += (ss[x].Contains(sf[y]) == true ? 1 : 0);
}
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For String.IndexOf()" ");
start = DateTime.Now;
Parallel.For(0, ss.Length,
() => 0,
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
{
subtotal += (ss[x].IndexOf(sf[y]) >= 0 ? 1 : 0);
}
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For Linq.Contains()" ");
start = DateTime.Now;
Parallel.For(0, sf.Length,
() => 0,
(x, loopState, subtotal) =>
{
subtotal += ss.Where(o => o.Contains(sf[x])).Count();
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For Linq.IndexOf()" ");
start = DateTime.Now;
Parallel.For(0, sf.Length,
() => 0,
(x, loopState, subtotal) =>
{
subtotal += ss.Where(o => o.IndexOf(sf[x]) > -1).Count();
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For Regex.IsMatch()" ");
start = DateTime.Now;
Parallel.For(0, ss.Length,
() => 0,
(x, loopState, subtotal) =>
{
for (int y = 0; y < sf.Length; y++)
{
subtotal += Regex.IsMatch(ss[x], Regex.Escape(sf[y])) == true ? 1 : 0;
}
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
total = 0;
Console.WriteLine("Starting method: "Parallel For AsParallel() Regex" ");
start = DateTime.Now;
Parallel.For(0, ss.Length,
() => 0,
(x, loopState, subtotal) =>
{
subtotal += sf.AsParallel().Sum(s => Regex.IsMatch(ss[x],
Regex.Escape(s)) ? 1 : 0);
return subtotal;
},
(s) =>
{
lock (lockObject)
{
total += s;
}
}
);
end = DateTime.Now;
Console.WriteLine("Finished at: " + end.ToLongTimeString());
Console.WriteLine("Time: " + (end - start));
Console.WriteLine("Total finds: " + total + Environment.NewLine);
Console.WriteLine();
Console.WriteLine("###########################################################");
Console.WriteLine();
Array.Clear(ss, 0, ss.Length);
ss = null;
Array.Clear(sf, 0, sf.Length);
sf = null;
Array.Clear(c, 0, c.Length);
c = null;
GC.Collect();
}
}
}