Ted*_*Ted -1 c# multithreading task async-await
我在这里发布了另一个 SO 问题,作为后续,我的同事做了一个测试,如下所示,作为 async/await/Tasks 参数的某种形式的“反击”。
(我知道lock不需要 on resultList,请忽略)
new Task().Start()会在 ThreadPool 上调度操作,并在 ThreadPool 上的不同线程上执行测试代码。这是否意味着第一次和第二次测试或多或少相同?(我猜不是,请解释async/await/Tasks 参数的某种形式的“计数器”。
发布的代码与asyncor完全无关await。它比较了三种不同的并行性:
前两者有一定的可比性。当然,直接线程池访问会比动态任务并行更快。但是这些测试没有表明直接线程池访问更难正确执行。特别是,当您运行实际代码并需要处理异常和返回值时,您必须将样板代码和对象实例添加到直接线程池访问代码中,这会减慢它的速度。
第三个完全没有可比性。它仅使用 10 个手动线程。同样,这个例子忽略了现实世界代码中必要的额外复杂性;具体来说,需要处理异常和返回值。它还假定分区大小,这是有问题的;现实世界的代码没有那么奢侈。如果您正在管理自己的线程集,那么您必须决定诸如当队列有很多项目时应该多快增加线程数,以及当队列为空时应该多快结束线程等事情。在您真正比较同一事物之前,这些都是困难的问题,它们会在 #3 测试中添加大量代码。
更不用说维护成本了。根据我的经验(即作为应用程序开发人员),微优化是不值得的。即使您采用“最差”(#1)方法,每个项目也会损失大约 7微秒。这是一个难以想象的小额储蓄。作为一般规则,开发人员时间对您的公司来说比用户时间更有价值。如果您的用户必须处理十万个项目,则几乎无法察觉差异。如果您采用“最佳”(#3)方法,则代码的可维护性将大大降低,特别是考虑到生产代码中所需的样板和线程管理代码,此处未显示。只需编写或阅读代码,就可以节省用户时间。
哦,所有这一切中最有趣的部分是,将所有这些不同类型的并行性进行比较,它们甚至没有包括最适合此测试的一种:PLINQ。
static void Main(string[] args)
{
TaskParallelLibrary();
ManualThreads();
Console.ReadKey();
}
static void ManualThreads()
{
var queue = new List<string>();
for (int i = 0; i != 1000000; ++i)
queue.Add("string" + i);
var resultList = new List<string>();
var stopwatch = Stopwatch.StartNew();
var counter = 0;
for (int i = 0; i != 10; ++i)
{
new Thread(() =>
{
while (true)
{
var t = "";
lock (queue)
{
if (counter >= queue.Count)
break;
t = queue[counter];
++counter;
}
t = t.Substring(0, 5);
string t2 = t.Substring(0, 2) + t;
lock (resultList)
resultList.Add(t2);
}
}).Start();
}
while (resultList.Count < queue.Count)
Thread.Sleep(1);
stopwatch.Stop();
Console.WriteLine($"Manual threads: Processed {resultList.Count} in {stopwatch.Elapsed}");
}
static void TaskParallelLibrary()
{
var queue = new List<string>();
for (int i = 0; i != 1000000; ++i)
queue.Add("string" + i);
var stopwatch = Stopwatch.StartNew();
var resultList = queue.AsParallel().Select(t =>
{
t = t.Substring(0, 5);
return t.Substring(0, 2) + t;
}).ToList();
stopwatch.Stop();
Console.WriteLine($"Parallel: Processed {resultList.Count} in {stopwatch.Elapsed}");
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上,多次运行此代码后,我发现 PLINQ 代码的性能比手动线程高出约 30%。.NET Core 3.0 preview5-27626-15 上的示例输出,专为 Release 构建,独立运行:
Parallel: Processed 1000000 in 00:00:00.3629408
Manual threads: Processed 1000000 in 00:00:00.5119985
Run Code Online (Sandbox Code Playgroud)
当然,PLINQ 代码是:
| 归档时间: |
|
| 查看次数: |
395 次 |
| 最近记录: |