Out of memory

0

Cześć,

Mam sobie program, który raz w miesiącu generuje całkiem spore CSV z danymi z DB (wymóg klienta).
Problem jest taki, że przy próbie wygenerowania jednej z CSV (ponad 1GB danych) dostaję OutOfMemory.

Aplikacja uruchamiana jest na serwerze mającym 190GB Ramu (z czego zawsze min 30 jest wolne) i nie bardzo wiem co mogę zrobić żeby to wyeliminować.

2020-12-06 21:07:18,669 ERROR [1] ReportService - System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Text.StringBuilder.ToString()
   at Logic.Services.ExportService.GenerateCsvFromDataTable(DataTable dt) in C:\GIT\serverapps\FundReports\FundReports\Logic\Services\ExportService.cs:line 63
   at Logic.Services.ReportService.PrepareReport(Procedure proc) in C:\GIT\serverapps\FundReports\FundReports\Logic\Services\ReportService.cs:line 224

Fragment kodu, generujący scv z DataTable:

public string GenerateCsvFromDataTable(DataTable dt)
        {
            var basePath = Path.GetTempPath();
            var path = Path.Combine(basePath, DateTime.Now.ToString("yyyy-MM-dd"));
            var finalPath = Path.Combine(path, Path.GetTempFileName() + ".csv").Replace("Pobierz", string.Empty);

            StringBuilder sb = new StringBuilder();

            IEnumerable<string> columnNames = dt.Columns.Cast<DataColumn>().
                                              Select(column => column.ColumnName);
            sb.AppendLine(string.Join(";", columnNames));

            foreach (DataRow row in dt.Rows)
            {
                IEnumerable<string> fields = row.ItemArray.Select(field =>
                  string.Concat("\"", field.ToString().Replace("\"", "\"\""), "\""));
                sb.AppendLine(string.Join(";", fields));
            }

            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            File.WriteAllText(finalPath, sb.ToString());
            return finalPath;
        }

Podejrzewam, że pewnie przerasta go ilość danych. Można to jakoś poprawić?

1

Aplikacja jest 32bitowa, albo korzysta z 32bitowych bibliotek, które maksymalnie są w stanie uciągnąć 2GB RAM.

10

dlaczego generujesz CAŁY plik w pamięci zamiast zapisywać linia po linii do pliku????

0

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-read-a-text-file-one-line-at-a-time

using (var sw = new StreamWriter(path))
{
    for (int i = 2; i <= 75; i++)
    {
        sw.WriteLine("Error_Flag = 'FOR_IMPORT' and location_type =   'Home' and batch_num = {0}", i);
    }
}
5

A mnie też teraz zaczęło zastanawiać dlaczego tego nie serializuje do csv za pomocą CsvHelper

0

Dziękuję Wam za odpowiedzi. Rzeczywiście, macie racje, trzymanie całego pliku w pamięci jest bez sensu. Działało to bez problemu przy mniejszych plikach, ale te raporty urosły na tyle, że trzeba to poprawić.

Dziękuję ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1