我正在开发一个程序,它从文件中获取信息,然后将它们存储在MySQL数据库中。这个MySQL数据库位于另一个专用服务器中,这个服务器比这个服务器强大得多。使用1gbps连接通过LAN发送数据。
它使用8个线程,因为我的服务器有8个核心,但不知怎的,它的运行速度很慢。
我的程序的CPU使用率仅为0-5% CPU亲和力全部是8个核心
那么,你有什么想法是错的,或者我怎样才能提高程序的速度?
更新
我更新了我的代码,它看起来更快:
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();
}
GetFile功能:
private string GetFile()
{
string file = "";
string source = "";
while (true)
{
if (this.data_files.Count() != 0)
{
file = this.data_files[0];
this.data_files.RemoveAt(0);
if (File.Exists(file) == true)
{
source = File.ReadAllText(file);
File.Delete(file);
break;
}
}
}
return source;
}
答案 0 :(得分:4)
我正在开发一个程序,它从文件中获取信息,然后将它们存储在MySQL数据库中。
显然你的程序不受CPU限制,它是IO绑定的。瓶颈将取决于您的硬盘和网络连接。甚至单个线程也可以确保正确使用这些资源(在设计良好的应用程序中)。添加额外的线程通常无济于事,它只会创建一堆线程,花费时间等待各种IO操作。
答案 1 :(得分:0)
使用所有硬件资源不是程序的正确目标。
相反,更好的目标是尽可能快地 。这是显着不同的。虽然使用更多的硬件资源可以提供帮助,但这并不总是足够的。
有时,为问题添加更多资源不会帮助。在那些情况下,不要。添加线程会使您的程序更复杂,但不一定更快,如您所见。
C#已经具有良好的TPL(你已经在使用)的异步编程功能,那么为什么不利用它?
这意味着.NET框架将以有效的方式自动为您管理线程。
这是我的建议:
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绑定的程序中,如果您使用锁,线程(和任务)也可能无法帮助您。 虽然锁有助于保持程序的良好运行,但它们的性能成本却很高。
在锁定中,一次只能执行一个线程。
这意味着第一个线程正在锁定_lock
实例,然后其他线程正在等待释放该锁。
在您的计划中,一次只有一个线程。
要解决此问题,请勿使用锁定。相反,编写完全不需要锁的程序。复制变量而不是共享它们。使用不可变集合而不是可变集合等等。
我上面的程序使用了完全零锁,因此可以更好地利用你的线程。