C# 程序不';不要使用所有的硬件资源
我正在开发一个程序,它从文件中获取信息,然后将它们存储在MySQL数据库中。这个MySQL数据库位于另一个专用服务器上,它比这里的服务器功能强大得多。使用1gbps连接通过LAN发送数据 它使用8个线程,因为我的服务器有8个内核,但不知为什么它运行得太慢了C# 程序不';不要使用所有的硬件资源,c#,multithreading,C#,Multithreading,我正在开发一个程序,它从文件中获取信息,然后将它们存储在MySQL数据库中。这个MySQL数据库位于另一个专用服务器上,它比这里的服务器功能强大得多。使用1gbps连接通过LAN发送数据 它使用8个线程,因为我的服务器有8个内核,但不知为什么它运行得太慢了 CPU为:英特尔至强E3-1270 v 3@3.50Ghz RAM:16gbecc 硬盘驱动器:SATA 3 1TB 我的程序的CPU使用率只有0-5% CPU亲和力全部为8核 那么,你有什么想法吗?我该如何提高程序的速度 更新: 我更新
- CPU为:英特尔至强E3-1270 v 3@3.50Ghz
- RAM:16gbecc
- 硬盘驱动器:SATA 3 1TB
Parallel.For(0, this.data_files.Count, new ParallelOptions { MaxDegreeOfParallelism = this.MaxThreads }, i =>
{
this.ThreadCount++;
this.ParseFile(this.GetSource());
});
以下是部署线程的代码片段:
while (true)
{
if (this.ThreadCount < this.MaxThreads)
{
Task.Factory.StartNew(() =>
this.ParseFile(this.GetFile())
);
this.ThreadCount++;
}
else
{
Thread.Sleep(1);
}
this.UpdateConsole();
}
我正在开发一个程序,它从文件中获取信息,然后将它们存储在MySQL数据库中
显然,您的程序不受CPU限制,而是受IO限制。瓶颈将取决于硬盘和网络连接。即使是单个线程也有可能确保这些资源的正确利用(在设计良好的应用程序中)。添加额外的线程通常不会有帮助,它只会创建一组线程,这些线程将花费时间等待各种IO操作。使用所有硬件资源不是程序的正确目标
相反,更好的目标是尽可能快地做到。这是明显不同的。虽然使用更多的硬件资源会有所帮助,但这并不总是足够的
有时,为问题添加更多资源是没有帮助的。在这种情况下,不要。添加线程会使程序更复杂,但不一定如您所见更快
C#已经在TPL(您已经在使用)中具有良好的异步编程特性,所以为什么不利用它呢
这意味着.NET framework将以高效的方式自动为您管理线程
以下是我的建议:
foreach (var file in GetFilesToRead()) {
var task = PerformOperation(file);
// Keep a list of tasks, if you wish.
}
...
Task PerformOperation (string filename) {
var file = await ReadFile(file);
await ParseFile(file);
DoSomething();
}
请注意,即使在CPU受限的程序中,如果使用锁,线程(和任务)也可能对您没有帮助。
虽然锁有助于保持程序的良好性能,但它们会带来巨大的性能代价
在锁中,一次只能执行一个线程
这意味着第一个线程正在锁定您的\u lock
实例,然后其他线程正在等待释放该锁
在您的程序中,一次只有一个线程处于活动状态
要解决这个问题,不要使用锁。相反,编写完全不需要锁的程序。复制变量而不是共享它们。使用不可变集合而不是可变集合等等
我上面的程序完全使用零锁,因此可以更好地利用线程。如果没有ParseFile\GetFile方法,很难判断瓶颈在哪里。但我怀疑这是文件系统的瓶颈。如果所有资源都这么容易利用,我们中的一些人就不会有工作了D:D:D您的程序可能是I/O绑定的。一般来说,从磁盘读取文件这样的操作非常慢,即使它们不太占用CPU。我用更多信息更新了我的帖子。在
GetFiles
中,你有lock
,它阻止所有其他线程读取不同的文件。这对多线程不太好,我添加了“获取文件”函数。我还用数据库更新了我的帖子information@Jason好的……这里的要点是,无论你做什么,你都不会有很高的CPU利用率。CPU时间对于您的程序来说不是稀缺资源,您拥有的CPU时间远远超过您的需要。如果你想让你的程序更快,你需要更有效地利用你的硬盘和网络连接。查看它们的利用率,并确保它们得到有效利用,并且只有在真正需要时才使用它们。嗯,磁盘唯一使用的是读取文件。。而且网络的速度足够快,所以不可能是网络的问题。最大IO大约为240kb/s@Jason从磁盘读取文件通常要比大多数CPU限制的操作花费几个数量级的时间。网络通信通常要比磁盘IO长几个数量级。即使你有一个快速的网络连接,它几乎肯定会成为瓶颈。对于这样一个程序,除了文件/网络IO之外,它实际上什么都做不了,因此CPU利用率不应该很高。这样做可能表明出了问题。@Jason关键是CPU利用率低不是问题。为了让程序运行得更快,您需要查看磁盘/网络利用率,如果其中一个(尤其是网络)利用率较低,请查看如何提高利用率。接下来看看减少或优化这些操作的方法,而不是CPU限制的操作。感谢您的精彩解释,我将尝试一下。我试过你的方法,但它告诉我上下文中不存在异步:也许将x数量的文件加载到列表中并从另一个线程监视它是有意义的,如果它需要更多的项目,它将加载更多
foreach (var file in GetFilesToRead()) {
var task = PerformOperation(file);
// Keep a list of tasks, if you wish.
}
...
Task PerformOperation (string filename) {
var file = await ReadFile(file);
await ParseFile(file);
DoSomething();
}