gpt4 book ai didi

c# - 为什么在此示例中线程会增加时间(降低性能)?

转载 作者:太空狗 更新时间:2023-10-29 20:42:39 25 4
gpt4 key购买 nike

这段代码:

  object obj = new object { };
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 90000; i++)
{
new Thread(() =>
{
lock (obj)
{
string file = new JavaScriptSerializer().Serialize(saeed);
File.AppendAllText(string.Format(@"c:\Temp\{0}.txt", i), file);
}
}).Start();
}
watch.Stop();

运行大约 15 分钟,而这段代码:

  Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 90000; i++)
{
{
string file = new JavaScriptSerializer().Serialize(saeed);
File.AppendAllText(string.Format(@"c:\Temp\{0}.txt", i), file);
}
}
watch.Stop();

运行大约 45 秒。为什么第一个应用程序在线程化时要慢得多?使用线程不是一种提高应用程序性能的技术吗?

更新:即使在我的线程中使用闭包概念并引用中间变量而不是 i 而不是使用锁,这使得线程真正异步,仍然创建那些文件需要超过 5 分钟。

  Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 90000; i++)
{
var x = i;
new Thread(() =>
{
string file = new JavaScriptSerializer().Serialize(saeed);
File.AppendAllText(string.Format(@"c:\Temp\{0}.txt", i), file);
}).Start();
}
watch.Stop();

最佳答案

1) 您目前正在创建 90000 个线程,这根本没有效率。不要每次都创建一个线程,而是使用线程池,这样你就可以重用已经创建的线程。请记住,创建线程需要一些时间和内存。

2) 你用lock 锁定了整个代码块,这意味着每个线程都被阻塞,直到另一个线程完成它的工作。所以你基本上在这里打败了多线程的全部目的。

3) 由于复杂的硬件相关原因(缓冲区等),磁盘 I/O 不能很好地与多线程一起工作。通常,多线程处理这部分代码并不是一个好主意。


关于磁盘 I/O 和多线程的评论:其实很复杂。

对于磁盘,磁盘臂必须移动才能在良好的扇区/柱面/磁道上读取/写入字节。如果你同时写入 2 个不同的文件(两个线程的情况,每个线程写入一个不同的文件),根据磁盘上的物理文件位置,你可能会要求你的磁盘臂从一个物理位置切换到另一个非常很快,这会破坏性能。在一个物理位置上为第一个文件写入多个磁盘扇区,然后将磁盘臂移动到另一个位置,然后为第二个文件写入一些磁盘扇区会更有效率.当您比较同时复制两个文件与复制一个文件,然后复制另一个文件的时间时,您可以看到这种效果。

因此对于这个非常基本的示例,性能增益/损失取决于:

  • 硬件本身。没有带 SSD 的磁盘臂,因此文件访问速度更快
  • 物理文件位置
  • 文件碎片
  • 缓冲。 disk buffer system有助于读取连续的 block ,如果您必须将 ARM 移动到另一个位置,这将无济于事。

我的谦虚建议:如果性能是您的主要目标,请尽量避免在多个线程中进行多次读/写。

关于c# - 为什么在此示例中线程会增加时间(降低性能)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17546724/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com