Сначала вам нужно очистить свой код, чтобы получить больше видимости, я сделал быстрый рефакторинг, и вот что я получил
const string FilePath = @"D:\Aggregate_Minute_AAPL.txt";
class SomeClass
{
public string Sym { get; set; }
public string Other { get; set; }
}
private void Something() {
File
.ReadLines(FilePath)
.AsParallel()
.Select(x => x.TrimStart('[').TrimEnd(']'))
.Select(JsonConvert.DeserializeObject<List<SomeClass>>)
.ForAll(WriteRecord);
}
private const string DirPath = @"D:\COMB1\MinuteAggregates";
private const string Separator = @",";
private void WriteRecord(List<SomeClass> data)
{
foreach (var item in data)
{
var fileNames = Directory
.GetFiles(DirPath, item.Sym+"_*.txt", SearchOption.AllDirectories);
foreach (var fileName in fileNames)
{
var fileLines = File.ReadAllLines(fileName)
.Skip(1).ToList();
var lastLine = fileLines.Last();
if (!lastLine.Contains(item.Sym))
{
fileLines.RemoveAt(fileLines.Count - 1);
}
fileLines.Add(
new StringBuilder()
.Append(item.Sym)
.Append(Separator)
.Append(item.Other)
.Append(Environment.NewLine)
.ToString()
);
File.WriteAllLines(fileName, fileLines);
}
}
}
Отсюда должно быть проще играть с List.AsParallel
, чтобы проверить, каки с какими параметрами код быстрее.
Также:
- Вы открываете файл записи дважды
- Удаление также несколько дорого, в индексе 0больше (однако, если есть несколько элементов, это не может иметь большого значения
if(fileNames.Length > 0)
бесполезно, используйте для, если список пуст, то он для просто пропустит - Вы можете попробовать StringBuilder вместо строковой интерполяции
Я надеюсь, что эти подсказки помогут вам улучшить ваше время и что я что-то не забыл.
Редактировать
В нашем каталоге около 10 000 файлов, поэтому, когда процесс запущен, он передает ошибку, что Процесс не может получить доступ к файлу, потому что он используется другим процессом
Хорошоесть ли апВозможно, что в ваших строках процесса есть дублированные имена файлов?
Если это так, вы можете попробовать простой подход, повторить попытку через несколько миллисекунд, что-то вроде
private const int SleepMillis = 5;
private const int MaxRetries = 3;
public void WriteFile(string fileName, string[] fileLines, int retries = 0)
{
try
{
File.WriteAllLines(fileName, fileLines);
}
catch(Exception e) //Catch the special type if you can
{
if (retries >= MaxRetries)
{
Console.WriteLine("Too many tries with no success");
throw; // rethrow exception
}
Thread.Sleep(SleepMillis);
WriteFile(fileName, fileLines, ++retries); // try again
}
}
Я пыталсядля простоты, но есть некоторые аннотации: - Если вы можете сделать ваши методы асинхронными , это может быть улучшением, изменив сон для Task.Delay , но вам нужнохорошо знать и понимать, как работает асинхронность - если коллизия часто случается, вам следует попробовать другой подход, например, параллельную карту с семафорами
Второе редактирование
В реальном сценарии я подключаюсь к websocket и получаю от 70 000 до 1 lac записей каждую минуту, а после этого я раздваиваю эти записи с данными потокового вещания и сохраняю их в своем собственном файле.И это становится медленнее, когда я применяю нашу концепцию с 11 000 файлов
Это сложная проблема, насколько я понимаю, вы говорите о 1166 записях в секунду, при таком размере мелкие детали могутстановятся большими узкими местами.
На этом этапе я думаю, что лучше подумать о других решениях, это может быть столько ввода-вывода для диска, может быть много потоков или слишком мало, сеть ...
Вы должны начать с профилирования приложения, чтобы проверить, где приложение тратит больше времени, чтобы сосредоточиться на этой области, сколько ресурсов использует?сколько у вас ресурсов?как память, процессор, сборщик мусора, сеть?У вас есть SSD?
Вам нужно четко понимать, что вас тормозит, чтобы вы могли атаковать это напрямую, это будет зависеть от многих вещей, с этой частью вам будет сложно помочь :(.
Существует тонн инструментов для профилей приложений c # и множество способов решения этой проблемы (распределение нагрузки на нескольких серверах, использование чего-то вроде redis для очень быстрого сохранения данных, какое-то событиехранить, чтобы вы могли использовать события ....