|
using System; |
|
using System.Collections.Generic; |
|
using System.Collections.Concurrent; |
|
using System.Text.RegularExpressions; |
|
using System.Linq; |
|
using System.Threading; |
|
using static System.Console; |
|
using Microsoft.FSharp.Core; |
|
using Microsoft.FSharp.Collections; |
|
|
|
namespace ConcurrentDictTest |
|
{ |
|
using TDictionary = ConcurrentDictionary<string, string>; |
|
//using TDictionary = Dictionary<string, string>; |
|
static class Program |
|
{ |
|
const int count = 1000000; |
|
static readonly TDictionary dict = new TDictionary(); |
|
|
|
static void Main() |
|
{ |
|
WriteLine("TEST #1 - Enumerate while adding"); |
|
WriteLine("-------------------------------------------------------------------------------"); |
|
WriteLine("Add many entries in one thread, while reading entries with other threads."); |
|
WriteLine(); |
|
MainAdd(); |
|
|
|
dict.Clear(); |
|
|
|
WriteLine(); |
|
WriteLine("TEST #2 - Enumerate while removing"); |
|
WriteLine("-------------------------------------------------------------------------------"); |
|
WriteLine("Remove many entries in one thread, while reading entries with other threads."); |
|
WriteLine(); |
|
MainRemove(); |
|
} |
|
|
|
static void MainAdd() |
|
{ |
|
var threads = new[] { |
|
new Thread(AddEntries), |
|
new Thread(EnumerateWithForeachCount), |
|
new Thread(EnumerateWithLinqCount), |
|
new Thread(EnumerateKeysWithLinqCount), |
|
new Thread(EnumerateWithFsharpCount), |
|
}; |
|
foreach (var t in threads) |
|
t.Start(); |
|
foreach (var t in threads) |
|
t.Join(); |
|
} |
|
|
|
static void MainRemove() |
|
{ |
|
AddEntries(); |
|
var threads = new[] { |
|
new Thread(RemoveEntries), |
|
new Thread(EnumerateWithForeach0), |
|
new Thread(EnumerateWithLinq0), |
|
new Thread(EnumerateKeysWithLinq0), |
|
new Thread(EnumerateWithFsharp0), |
|
}; |
|
foreach (var t in threads) |
|
t.Start(); |
|
foreach (var t in threads) |
|
t.Join(); |
|
} |
|
|
|
static void EnumerateWithForeach0() => EnumerateWithForeach(0); |
|
static void EnumerateWithForeachCount() => EnumerateWithForeach(count); |
|
static void EnumerateWithForeach(int expectedCount) |
|
{ |
|
try |
|
{ |
|
int ct; |
|
do |
|
{ |
|
ct = 0; |
|
foreach(var item in dict) |
|
{ |
|
if(item.Key == null) |
|
throw new Exception("Somehow the dictionary returned a null."); // "use" the item. |
|
ct++; |
|
} |
|
} while (ct != expectedCount); |
|
WriteBullet("Foreach - Successfully enumerated. Count: " + ct); |
|
} |
|
catch(Exception e) |
|
{ |
|
WriteBullet("Foreach - Failed with:\r\n " + e); |
|
} |
|
} |
|
|
|
static void EnumerateWithLinq0() => EnumerateWithLinq(0); |
|
static void EnumerateWithLinqCount() => EnumerateWithLinq(count); |
|
static void EnumerateWithLinq(int expectedCount) |
|
{ |
|
try |
|
{ |
|
var items = dict.ToList(); |
|
do |
|
{ |
|
items = dict |
|
//.Where(x => true) |
|
.ToList(); |
|
foreach(var item in items) |
|
{ |
|
if(item.Key == null) |
|
throw new Exception("Somehow the dictionary returned a null."); // "use" the item. |
|
} |
|
} while (items.Count() != expectedCount); |
|
WriteBullet("Linq - Successfully enumerated. Count: " + items.Count()); |
|
} |
|
catch(Exception e) |
|
{ |
|
WriteBullet("Linq - Failed with:\r\n " + e); |
|
} |
|
} |
|
|
|
static void EnumerateKeysWithLinq0() => EnumerateKeysWithLinq(0); |
|
static void EnumerateKeysWithLinqCount() => EnumerateKeysWithLinq(count); |
|
static void EnumerateKeysWithLinq(int expectedCount) |
|
{ |
|
try |
|
{ |
|
WriteBullet($".Keys is {(dict.Keys is System.Collections.ICollection ? "" : "not ")} an ICollection."); |
|
WriteBullet($".Keys is {(dict.Keys is ICollection<string> ? "" : "not ")} an ICollection<string>."); |
|
WriteBullet($".Keys is {(dict.Keys is IList<string> ? "" : "not ")} an IList<string>."); |
|
var items = dict.Keys.ToList(); |
|
do |
|
{ |
|
items = dict.Keys |
|
//.Where(x => true) |
|
.ToList(); |
|
foreach (var item in items) |
|
{ |
|
if (item == null) |
|
throw new Exception("Somehow the dictionary returned a null key."); // "use" the item. |
|
} |
|
} while (items.Count() != expectedCount); |
|
WriteBullet("Keys.ToList() - Successfully enumerated keys. Count: " + items.Count()); |
|
} |
|
catch (Exception e) |
|
{ |
|
WriteBullet("Keys.ToList() - Failed with:\r\n " + e); |
|
} |
|
} |
|
|
|
static void EnumerateWithFsharp0() => EnumerateWithFsharp(0); |
|
static void EnumerateWithFsharpCount() => EnumerateWithFsharp(count); |
|
static void EnumerateWithFsharp(int expectedCount) |
|
{ |
|
Converter<KeyValuePair<int, int>, bool> converter = x => true; |
|
try |
|
{ |
|
var items = ListModule.OfSeq(dict); |
|
do |
|
{ |
|
items = ListModule.OfSeq( |
|
//SeqModule.Where( |
|
//FSharpFunc<KeyValuePair<int, int>, bool>.FromConverter(converter), |
|
dict) |
|
//) |
|
; |
|
foreach(var item in items) |
|
{ |
|
if(item.Key == null) |
|
throw new Exception("Somehow the dictionary returned a null."); // "use" the item. |
|
} |
|
} while (items.Count() != expectedCount); |
|
WriteBullet("F# - Successfully enumerated. Count: " + items.Count()); |
|
} |
|
catch (Exception e) |
|
{ |
|
WriteBullet("F# - Failed with:\r\n " + e); |
|
} |
|
} |
|
|
|
static void AddEntries() |
|
{ |
|
for(int i = 0; i < count; i++) |
|
dict[i.ToString()] = i.ToString(); |
|
WriteBullet("Done adding " + dict.Count); |
|
} |
|
|
|
static void RemoveEntries() |
|
{ |
|
RemoveEntriesHashcode(); |
|
WriteBullet("Done removing. Count: " + dict.Count); |
|
} |
|
|
|
static void RemoveEntriesAscending() => |
|
RemoveEntries(Enumerable.Range(0, count)); |
|
|
|
static void RemoveEntriesDescending() => |
|
RemoveEntries(Enumerable.Range(0, count).Reverse()); |
|
|
|
static void RemoveEntriesHashcode() => |
|
RemoveEntries(Enumerable.Range(0, count).OrderBy(i => i.GetHashCode())); |
|
|
|
static void RemoveEntries(IEnumerable<int> entryKeys) |
|
{ |
|
string _ignoredValue; |
|
foreach (int i in entryKeys) |
|
//dict.Remove(i); |
|
dict.TryRemove(i.ToString(), out _ignoredValue); |
|
} |
|
|
|
static void WriteBullet(string s) => |
|
WriteLine( |
|
Regex.Replace(s, @"(?<=^\u0020*)\b", "* ", RegexOptions.Multiline) |
|
.Replace("`", "`") |
|
.Replace("[", "[") |
|
.Replace("]", "]")); |
|
} |
|
} |