Håller med Jurand och VB om att det är smidigast att vid faktiskt användning sortera/filtrera data t.ex. med hjälp av LINQ. Relativt snabbt går det också. Satte ihop ett litet test och parallel LINQ har riktigt bra prestanda. Inriktade mig på att få så jämförelsebara värden mellan test typerna som möjligt, och inte att få bästa möjliga prestande.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Zoomware.Examples.SortedData01
{
class Program
{
static void Main ( string [] args )
{
// do a dummy restart to remove any creation penelties..
stopwatch.Restart ( );
// note: consider first iteration as a warm-up..
foreach ( var samples in new int [] { 10, 10, 100, 500, 1000, 5000, 50000, 250000, 1000000 } )
{
var holder = SampleHolder.Generate ( samples );
for ( var i = 1; i <= 3; i++ )
{
BenchmarkSortedList ( holder, i );
BenchmarkListWithObject ( holder, i );
BenchmarkDictionary ( holder, i );
// parallel orderby with .NET 4.0
BenchmarkListWithObjectAndPLinq ( holder, i );
}
}
}
static void BenchmarkSortedList ( SampleHolder holder, int iteration )
{
var list = new SortedList<int,string> ( holder.Samples.Count );
stopwatch.Restart ( );
foreach ( var sample in holder.Samples )
list.Add ( sample.Key, sample.Value );
var dummy = 0;
foreach ( var sample in list )
dummy += sample.Key;
var elapsed = stopwatch.Elapsed;
Console.WriteLine ( "#{0} SortedList took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]",
iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy );
}
static void BenchmarkListWithObject ( SampleHolder holder, int iteration )
{
var list = new List<KeyValuePair<int, string>> ( holder.Samples.Count );
stopwatch.Restart ( );
foreach ( var sample in holder.Samples )
list.Add ( new KeyValuePair<int,string> ( sample.Key, sample.Value ) );
var dummy = 0;
foreach ( var sample in list.OrderBy ( kv => kv.Key ) )
dummy += sample.Key;
var elapsed = stopwatch.Elapsed;
Console.WriteLine ( "#{0} List with class took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]",
iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy );
}
static void BenchmarkListWithObjectAndPLinq ( SampleHolder holder, int iteration )
{
var list = new List<KeyValuePair<int, string>> ( holder.Samples.Count );
stopwatch.Restart ( );
foreach ( var sample in holder.Samples )
list.Add ( new KeyValuePair<int, string> ( sample.Key, sample.Value ) );
var dummy = 0;
foreach ( var sample in list.AsParallel().OrderBy ( kv => kv.Key ) )
dummy += sample.Key;
var elapsed = stopwatch.Elapsed;
Console.WriteLine ( "#{0} List with class and PLinq took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]",
iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy );
}
static void BenchmarkDictionary ( SampleHolder holder, int iteration )
{
var dictionary = new Dictionary<int, string> ( holder.Samples.Count );
dictionary.Count ( );
stopwatch.Restart ( );
foreach ( var sample in holder.Samples )
dictionary.Add ( sample.Key, sample.Value );
var dummy = 0;
foreach ( var sample in dictionary.OrderBy ( kv => kv.Key ) )
dummy += sample.Key;
var elapsed = stopwatch.Elapsed;
Console.WriteLine ( "#{0} Dictionary took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]",
iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy );
}
static Stopwatch stopwatch = new Stopwatch ( );
}
class SampleHolder
{
public static SampleHolder Generate ( int numberOfSamples )
{
var holder = new SampleHolder ( )
{
Samples = new List<KeyValuePair<int, string>> ( numberOfSamples )
};
for ( int i = 0; i < numberOfSamples; ++i )
holder.AddSample ( );
// remove duplicate integers. (ordinary dictionaries cannot handle them)
holder.Samples = holder.Samples
.GroupBy ( kv => kv.Key )
.Select ( group => group.First ( ) )
.ToList ( );
return holder;
}
public void AddSample ( )
{
// feed kvp with random values..
Samples.Add ( new KeyValuePair<int, string> ( randomizer.Next ( ), randomizer.Next ( ).ToString ( ) ) );
}
public List<KeyValuePair<int, string>> Samples { get; set; }
static Random randomizer = new Random ( );
}
}