Я использую .NET 8.0, и это мой код program.cs:
Код: Выделить всё
using System.Data;
using System.Diagnostics;
Console.WriteLine("Generating sample DataTable...");
var stopwatch = Stopwatch.StartNew();
DataTable table = GenerateLargeSampleTable(1_000_000, 100);
stopwatch.Stop();
Console.WriteLine($"DataTable generated in {stopwatch.Elapsed.TotalSeconds:F2} seconds.");
Console.ReadLine();
static DataTable GenerateLargeSampleTable(int rowCount, int columnCount)
{
var table = new DataTable("SampleData");
var rand = new Random();
for (int i = 0; i < columnCount; i++)
{
if (i % 3 == 0)
table.Columns.Add($"StringCol_{i}", typeof(string));
else if (i % 3 == 1)
table.Columns.Add($"NumberCol_{i}", typeof(double));
else
table.Columns.Add($"DateCol_{i}", typeof(DateTime));
}
table.BeginLoadData();
for (int r = 0; r < rowCount; r++)
{
var row = table.NewRow();
for (int c = 0; c < columnCount; c++)
{
switch (table.Columns[c].DataType.Name)
{
case nameof(String):
row[c] = $"Text_{r}_{c}";
break;
case nameof(Double):
row[c] = Math.Round(rand.NextDouble() * 10000, 2);
break;
case nameof(DateTime):
row[c] = DateTime.Now.AddDays(-rand.Next(0, 3650));
break;
}
}
table.Rows.Add(row);
}
table.EndLoadData();
return table;
}

Но он занимает около 40 секунд при запуске из файла .exe после публикация:

Это мой профиль публикации:

Я думал, что запуск опубликованной версии должен быть быстрее, а не медленнее, поскольку не работают инструменты отладки. Может кто-нибудь сказать мне, что происходит?
Примечания: мое устройство работает под управлением Windows Home с процессором Intel Core i9 12-го поколения и 32 ГБ оперативной памяти. Я использую Visual Studio 2022.
Поскольку Марк считает, что DataTable — плохой выбор, я меняю код на более простой (добавляю строки в список). Я также создал более обширный журнал, как предложил Альпарсиан, и, поскольку подозреваю, что консоль может быть источником проблем с производительностью, я создаю класс AsyncLogger для асинхронной записи в консоль.
Это мой новый код program.cs:
Код: Выделить всё
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
for (int i = 0; i < 10; i++)
{
AsyncLogger.Log($"Generating sample data, rep: {i}...");
var totalWatch = Stopwatch.StartNew();
var data = GenerateLargeDynamicData(1_000_000, 1000);
totalWatch.Stop();
AsyncLogger.Log($"Data generated in {totalWatch.Elapsed.TotalSeconds:F2} seconds total.");
AsyncLogger.Log($"Total rows: {data.Count:N0}");
GC.Collect();
long mem = GC.GetTotalMemory(forceFullCollection: true);
AsyncLogger.Log($"Current memory usage: {mem / 1024 / 1024} MB");
}
// Wait for all log messages to complete
await AsyncLogger.FlushAsync();
Console.ReadLine();
static List GenerateLargeDynamicData(int rowCount, int columnCount)
{
AsyncLogger.Log($"[Start] Generating {rowCount:N0} strings of length {columnCount:N0}...");
var totalWatch = Stopwatch.StartNew();
var stepWatch = Stopwatch.StartNew();
List data = new List();
stepWatch.Stop();
AsyncLogger.Log($"[Timing] List initialized in {stepWatch.Elapsed.TotalMilliseconds:F3} ms");
stepWatch.Restart();
int batchSize = 100_000;
int batchCount = 0;
var batchWatch = Stopwatch.StartNew();
for (int i = 0; i < rowCount; i++)
{
data.Add(new string('X', columnCount));
if ((i + 1) % batchSize == 0)
{
batchCount++;
AsyncLogger.Log($"[Batch {batchCount}] Generated {i + 1:N0}/{rowCount:N0} items — " +
$"{batchWatch.Elapsed.TotalSeconds:F2}s elapsed " +
$"(avg {batchWatch.Elapsed.TotalMilliseconds / batchSize:F4} ms/item)");
batchWatch.Restart();
}
}
stepWatch.Stop();
AsyncLogger.Log($"[Timing] String generation: {stepWatch.Elapsed.TotalSeconds:F3}s");
totalWatch.Stop();
AsyncLogger.Log($"[Timing] Total execution time: {totalWatch.Elapsed.TotalSeconds:F3}s");
return data;
}
static class AsyncLogger
{
private static readonly BlockingCollection _logQueue = new();
private static readonly Task _loggingTask;
static AsyncLogger()
{
_loggingTask = Task.Run(async () =>
{
foreach (var msg in _logQueue.GetConsumingEnumerable())
{
await Console.Out.WriteLineAsync(msg);
}
});
}
public static void Log(string message)
{
// Don’t block — drop message if queue is too full
if (_logQueue.Count < 10_000)
_logQueue.Add(message);
}
public static async Task FlushAsync()
{
// Wait until all messages processed
_logQueue.CompleteAdding();
await _loggingTask;
}
}
Это результат отладки Visual Studio.

И это результат исполняемого файла отладки (теперь я запускаю исполняемый файл из папки отладки, так как подозреваю, что опубликуйте, добавьте что-нибудь, что замедлит работу).

Медленная часть не только в генерации данных цикла, но и инициализация списка также медленнее. Я подозреваю, что это вызвано распределением памяти.
Подробнее здесь: https://stackoverflow.com/questions/797 ... er-publish
Мобильная версия