Parallel.ForEach 升级服务器后变慢
Parallel.ForEach slower after upgrading server
我每天在 20 个文件夹上运行 it.There 中有 60k+ 文件的进程没有子文件夹,每个文件夹中的输入文件只有几 MB size.For,我读取文件,解析它并将一些数据写入单独的输出文件(即 20 个输出文件)。我最近升级了我们的服务器(更高的内核和更高的内存)并注意到 performance.I 急剧下降希望有人能指出我的问题。
下面是我的代码
int iFolderCount = 0;
DirectoryInfo oSourceFolder = new DirectoryInfo(sInputFolder);
DirectoryInfo[] oIdDirectoryList = oSourceFolder.GetDirectories().Where(Id => sFolderList.Contains(Id.Name.ToUpper())).ToArray<DirectoryInfo>();
Parallel.ForEach(oIdDirectoryList, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (oId, state) =>
{
FileInfo[] sFileList = oId.GetFiles();
RawCounter.GetOrAdd(oId.Name.ToUpper(), sFileList.Length);
using (StreamWriter oHandoffWriter = new StreamWriter(new FileStream(string.Format("{0}{1}_{2}_{3}{4}", sOutputFolder, Day, sOutputFileName, Interlocked.Increment(ref iFolderCount), HANDOFF_FILE_EXTENSION),FileMode.Append,FileAccess.Write,FileShare.Write)))
{
int iFileCounter = 0;
foreach (FileInfo oFileInfo in sFileList)
{
try
{
ProcessFile(oFileInfo, oHandoffWriter);
iFileCounter++;
}
catch (Exception ex)
{
oLog.Info("Failed to process file " + oFileInfo.Name);
oLog.Info(ex.Message);
oLog.Info(ex.StackTrace);
oLog.Info(ex.InnerException);
File.Copy(oFileInfo.FullName, sErrorFileFolderPath + oFileInfo.Name, true);
}
}
ProcessedCounter.GetOrAdd(oId.Name.ToUpper(), iFileCounter);
}
});
将进程移动到新服务器后,我注意到 performance.We 急剧下降,从 8 核变为 36 核,从 8GB RAM 变为 128GB RAM。
我开始降低并行度并注意到每次降低并行度时进程的性能都更好。
MaxDegreeOfParallelism = 2
通过将其设置为 2,我看到更高 performance.What 我在这里失踪了吗? MaxDegreeOfParallelism = Environment.ProcessorCount 在旧服务器 运行 windows server 2008, 8 Core,8GB RAM 上更快,而 MaxDegreeOfParallelism = 2 在新 windows server 2012,32 Core 上更快,128 GB 内存。
编辑:我同意进程是 IO intensive.The 每日文件 count/size 变化不大。以下是旧服务器上该过程的完整时间。
- 20151028.The 天的交接完成,过程耗时 504.05125171 分钟。
- 20151027.The 天的交接完成,过程耗时 504.37106602 分钟。
- 20151026.The 天的交接完成,过程耗时 549.76132134 分钟。
- 第 20151025.The 天完成的交接过程耗时 541.97557402 分钟。
- 第 20151024.The 天完成的交接过程耗时 567.14474476 分钟。
- 20151023.The 天的交接完成,过程耗时 513.51368027 分钟。
- 20151022.The 天的交接完成,过程耗时 595.21733215 分钟。
在我使用的新服务器上 Environment.ProcessorCount
- 完成第 20151118.The 天的交接过程花费了 712.05125171 分钟。
在新服务器上,当我使用2作为并行度时
- 完成第 20151118.The 天的交接过程花费了 89.61782427 分钟。
我会做更多的运行并更新这个问题。
处理既不是 CPU 也不是内存限制,因此新服务器根本没有帮助。似乎 IO 绑定了。 IO硬件有变化吗?并行加上 IO 很容易意味着性能变慢,因为顺序 IO 可能会变成随机 IO。
根据CPU核数来选择IO的DOP是错误的。最佳 IO DOP 与内核数无关。根据经验确定最佳 DOP。
我每天在 20 个文件夹上运行 it.There 中有 60k+ 文件的进程没有子文件夹,每个文件夹中的输入文件只有几 MB size.For,我读取文件,解析它并将一些数据写入单独的输出文件(即 20 个输出文件)。我最近升级了我们的服务器(更高的内核和更高的内存)并注意到 performance.I 急剧下降希望有人能指出我的问题。
下面是我的代码
int iFolderCount = 0;
DirectoryInfo oSourceFolder = new DirectoryInfo(sInputFolder);
DirectoryInfo[] oIdDirectoryList = oSourceFolder.GetDirectories().Where(Id => sFolderList.Contains(Id.Name.ToUpper())).ToArray<DirectoryInfo>();
Parallel.ForEach(oIdDirectoryList, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (oId, state) =>
{
FileInfo[] sFileList = oId.GetFiles();
RawCounter.GetOrAdd(oId.Name.ToUpper(), sFileList.Length);
using (StreamWriter oHandoffWriter = new StreamWriter(new FileStream(string.Format("{0}{1}_{2}_{3}{4}", sOutputFolder, Day, sOutputFileName, Interlocked.Increment(ref iFolderCount), HANDOFF_FILE_EXTENSION),FileMode.Append,FileAccess.Write,FileShare.Write)))
{
int iFileCounter = 0;
foreach (FileInfo oFileInfo in sFileList)
{
try
{
ProcessFile(oFileInfo, oHandoffWriter);
iFileCounter++;
}
catch (Exception ex)
{
oLog.Info("Failed to process file " + oFileInfo.Name);
oLog.Info(ex.Message);
oLog.Info(ex.StackTrace);
oLog.Info(ex.InnerException);
File.Copy(oFileInfo.FullName, sErrorFileFolderPath + oFileInfo.Name, true);
}
}
ProcessedCounter.GetOrAdd(oId.Name.ToUpper(), iFileCounter);
}
});
将进程移动到新服务器后,我注意到 performance.We 急剧下降,从 8 核变为 36 核,从 8GB RAM 变为 128GB RAM。
我开始降低并行度并注意到每次降低并行度时进程的性能都更好。
MaxDegreeOfParallelism = 2
通过将其设置为 2,我看到更高 performance.What 我在这里失踪了吗? MaxDegreeOfParallelism = Environment.ProcessorCount 在旧服务器 运行 windows server 2008, 8 Core,8GB RAM 上更快,而 MaxDegreeOfParallelism = 2 在新 windows server 2012,32 Core 上更快,128 GB 内存。
编辑:我同意进程是 IO intensive.The 每日文件 count/size 变化不大。以下是旧服务器上该过程的完整时间。
- 20151028.The 天的交接完成,过程耗时 504.05125171 分钟。
- 20151027.The 天的交接完成,过程耗时 504.37106602 分钟。
- 20151026.The 天的交接完成,过程耗时 549.76132134 分钟。
- 第 20151025.The 天完成的交接过程耗时 541.97557402 分钟。
- 第 20151024.The 天完成的交接过程耗时 567.14474476 分钟。
- 20151023.The 天的交接完成,过程耗时 513.51368027 分钟。
- 20151022.The 天的交接完成,过程耗时 595.21733215 分钟。
在我使用的新服务器上 Environment.ProcessorCount
- 完成第 20151118.The 天的交接过程花费了 712.05125171 分钟。
在新服务器上,当我使用2作为并行度时
- 完成第 20151118.The 天的交接过程花费了 89.61782427 分钟。
我会做更多的运行并更新这个问题。
处理既不是 CPU 也不是内存限制,因此新服务器根本没有帮助。似乎 IO 绑定了。 IO硬件有变化吗?并行加上 IO 很容易意味着性能变慢,因为顺序 IO 可能会变成随机 IO。
根据CPU核数来选择IO的DOP是错误的。最佳 IO DOP 与内核数无关。根据经验确定最佳 DOP。