.Net 中Partitioner static与dynamic的性能对比


先看LINQ的方式,dynamic的方式:

void Main()
{
	// testing setup
	var source = Enumerable.Range(0, 10000000).ToArray();
	double[] results = new double[source.Length];
	
	Console.WriteLine("creating partitioner in LINQ way...");
	var dt = DateTime.Now;
	var partitionerLinq = Partitioner.Create(source, true);
	Console.WriteLine("creating partitioner in LINQ done, ticks: " + (DateTime.Now - dt).Ticks);
	
	dt = DateTime.Now;
	var r = partitionerLinq.AsParallel().Select(x => x * x * Math.PI).ToList();
	Console.WriteLine("LINQ way done , ticks:" + (DateTime.Now - dt).Ticks);
	


	dt =  DateTime.Now;


	for(var i = 0;i < source.Length; i++){
		results[i] = source[i] * Math.PI;
	}
	
	Console.WriteLine("processing by single thread done, ticks : " + (DateTime.Now - dt).Ticks);
}




LINQPAD输出:
creating partitioner in LINQ way...
creating partitioner in LINQ done, ticks: 0
LINQ way done , ticks:3472754
processing by single thread done, ticks : 380298


可见,动态分配chunk的partition基本比单线程的普通实现慢了10倍!


再看静态的方式:

void Main()
{
	// testing setup
	var source = Enumerable.Range(0, 10000000).ToArray();
	double[] results = new double[source.Length];
	
	Console.WriteLine("creating partitioner in a way processing as static range ..");
	var dt = DateTime.Now;
	// Partition the entire source array.
	var rangePartitioner = Partitioner.Create(0, source.Length);
	
	Console.WriteLine("created partitioner, ticks:" + (DateTime.Now - dt).Ticks);


	dt =  DateTime.Now;
	// Loop over the partitions in parallel.
	Parallel.ForEach(rangePartitioner, (range, loopState) =>
	{
		// Loop over each range element without a delegate invocation.
		for (int i = range.Item1; i < range.Item2; i++)
		{
			results[i] = source[i] * source[i] * Math.PI;
		}
	});
	Console.WriteLine("processing by range partitioner done, ticks : " + (DateTime.Now - dt).Ticks);
	
	dt =  DateTime.Now;


	for(var i = 0;i < source.Length; i++){
		results[i] = source[i] * Math.PI;
	}
	
	Console.WriteLine("processing by single thread done, ticks : " + (DateTime.Now - dt).Ticks);
}


// Define other methods and classes here




LINQPAD输出:

creating partitioner in a way processing as static range ..
created partitioner, ticks:0
processing by range partitioner done, ticks : 185180
processing by single thread done, ticks : 375279


基本上,静态partition的方式比普通方式快两倍。


现在,依然使用静态方式,把数据量增大10倍,看LINQ输出:

creating partitioner in a way processing as static range ..
created partitioner, ticks:0
processing by range partitioner done, ticks : 1951457
processing by single thread done, ticks : 3808162




可以看到,时间差别依然差不多是一倍的速度。




总结,当考虑使用Partition时,最好使用静态方式;并且处理逻辑不建议过于复杂(MSDN建议:In general, range partitioning is only faster when the execution time of the delegate is small to moderate);不过这一点还有待测试,暂时没有想出合适的logic来测试。

你可能感兴趣的:(.Net 中Partitioner static与dynamic的性能对比)