#c# #filestream #streamwriter
#c# #файловый поток #streamwriter
Вопрос:
Я создаю выходной файл HTML на C #, хотя скорость работы с файлами размером 60 Мб кажется невероятно высокой. Создание файла занимает 20 минут, что является очень медленным процессом. Ранее около 35 Мб он создавался за 5 секунд, поэтому я не уверен, что здесь вызывает задержку.
Сначала я бы использовал эти строки, чтобы начать генерировать отчет:
public static void GenerateHtmlReport()
{
GenerateFinalResults();
HtmlFileName ??= "Report-" $"{DateTime.Now:dd_MMM_yyyy-[HH_mm]}" ".html";
var fileName = Path.Combine(GetRootFolder(), HtmlFileName);
using var fs = new FileStream(fileName, FileMode.Create);
using var w = new StreamWriter(fs, Encoding.UTF8);
w.WriteLine(RenderHtml.ContructReportHeader(User));
RenderHtml.ConstructHtmlBody(Results, w);
w.WriteLine(RenderHtml.ConstructFullSummaryReport(Results));
w.WriteLine(RenderHtml.ContructDashboard(Results, ResultStart));
}
Если я записываю в файл полную строку, то это занимает довольно много времени, тем не менее запись ее по частям, на мой взгляд, не намного полезнее.
Хотя это приводит меня к двум вопросам
- Какой процесс был бы быстрее — запись целой строки или небольших фрагментов?
- есть ли другой метод записи файлов, который я должен использовать для ускорения производительности?
С уважением,
Комментарии:
1. Почему бы вам не сравнить это? Хотя я сомневаюсь, что вы заметите какую-либо разницу, поскольку StreamWriter использует внутренний буфер 1K, а FileStream по умолчанию использует буфер 4K. Оба размера могут быть изменены
2. Что вы подразумеваете под этим тестом?
3. Это означает, что фактически измеряется время, затраченное в каждом случае. Если вам нужно 20 минут для 60 МБ, проблема не имеет ничего общего с файлами. Я бы предположил, что приложение использует неэффективные операции со строками, создавая множество временных строк, которые необходимо собирать для мусора. Даже тогда от 5 секунд до 20 минут — это много.
4. Вместо того, чтобы угадывать, профилируйте свое приложение. В самой Visual Studio вы можете проверить использование процессора и памяти приложением во время его работы. Если вы видите постоянно увеличивающееся использование памяти или изображение бензопилы, проблема действительно связана с памятью и сборкой мусора. Строки неизменяемы, поэтому любая операция модификации строки создает новую строку, которую в конечном итоге необходимо скопировать. Добавление большого количества элементов в список<T> без указания емкости также приводит к перераспределению
5. Я подозреваю, что если вы перепишете свой код, чтобы можно было переходить через функции, вы поймете, что задержка возникает из
RenderHtml.ContructReportHeader(User)
,RenderHtml.ConstructFullSummaryReport(Results)
аRenderHtml.ContructDashboard(Results, ResultStart)
не изWriteLine
. Если какой-либо из этих методов генерирует что-то большее, чем одну короткую строку, он должен записывать выходные данные непосредственно в writer вместо буферизации 60 МБ текста в памяти, чтобы записать его в конце
Ответ №1:
Ответ действительно является StringBuilder . Внесение изменений во все части кода вместо использования (конкатенация) Я подал в суд на StringBuilder.Append() и вернул его обратно в виде строки. Теперь отчет создается менее чем за 5 секунд вместо 22 минут. Так что это огромное улучшение.
Комментарии:
1. Не совсем. Нет необходимости хранить 60 МБ текста в памяти (в StringBuilder). Вместо
stringBuilder.Append
этого может быть записано непосредственно в поток с помощьюstreamWriter.Write
.2. Мы бы не хранили все это в памяти, а логическими блоками, и на следующей итерации оно снова стало бы пустым. Хотя. да, мы могли бы вместо этого записать все в файл, но это работает для меня.