У меня есть ежедневный процесс, который работает в 20 папках с 60k + файлами в нем. Нет подпапок, а входных файлов - не более МБ. Для каждой папки я читаю файлы, разбираю он и записывает некоторые данные в отдельный выходной файл (т. е. 20 выходных файлов). Недавно я обновил наш сервер (более высокие ядравыше памяти) и заметил резкое снижение производительности. Надеюсь, кто-то может указать мне на проблему.Parallel.ForEach медленнее после обновления сервера
Ниже мой код
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 ядер и 8 Гб оперативной памяти, до 128 Гб оперативной памяти.
Я начал уменьшения степени параллелизма и заметил, что процесс выполняется лучше каждый раз, я уменьшил степень параллельности.
MaxDegreeOfParallelism = 2
Установив его в 2, я вижу более высокую производительность. Что мне здесь не хватает? MaxDegreeOfParallelism = Environment.ProcessorCount работает быстрее на более старом сервере с сервером Windows 2008, 8 Core, 8 ГБ, а MaxDegreeOfParallelism = 2 быстрее на новом сервере Windows 2012, 32 Core, 128 ГБ оперативной памяти.
EDIT: Я согласен с тем, что процесс имеет интенсивный объем ввода-вывода. Ежедневный размер файла/размер файла не сильно отличается. Ниже приведены полные времена для процесса на старом сервере.
- Передача обслуживания завершена на день 20151028. Процесс потребовался 504.05125171 минут.
- Передача обслуживания завершена на день 20151027. Процесс занял 504.37106602 минут.
- Передача обслуживания завершена на день 20151026. Процесс занимает 549.76132134 минут.
- Передача обслуживания завершена на день 20151025. Процесс занимает 541.97557402 минут.
- Передача обслуживания завершена на день 20151024. Процесс занимает 567.14474476 минут.
- Передача обслуживания завершена на день 20151023. Процесс обработан 513.51368027 минут.
- Передача обслуживания завершена на день 20151022. Процесс составил 595.21733215 минут.
На новом сервере, когда я использовал Environment.ProcessorCount
- хэндовера завершена за день 20151118.The процесс занял +712,05125171 минут.
На новом сервере, когда я использовал как степень параллельности
- хэндовера завершена за день 20151118.The процесс занял +89,61782427 минут.
Я сделаю больше запусков и обновит этот вопрос.
Похоже, вы задыхаетесь от ввода-вывода. Как ваши диски? – spender