Я записываю огромное количество данных в таблицу Azure из консольного приложения на C #.Это делает следующее
- Открытие соединения с уже существующей таблицей.
- Считывает файл с помощью StreamReader
- Собирает 100 запросов одновременно и выполняет пакетную записьв таблицу.
Один процесс имеет скорость записи около 500-700 / с без распараллеливания, а для записи 1 миллиарда записей потребуется около 30 дней.Для оптимизации я сделал следующее:
- Создал 20 процессов, выполняющих вышеуказанный exe-файл, и он работал параллельно без каких-либо проблем, сократив время записи до 1,5 дня.[Идеальный сценарий, который я не могу сделать, к сожалению, из-за ограничений в нашей кодовой базе]
6 ядер / 12 логических процессоров:
+----------+---------------------------------+--------+------------------------------------
| #process | Time per process per 10k writes | W/s | Total time in hours (1.3b queries) |
+----------+---------------------------------+--------+------------------------------------+
| 2 | 14.2s/10k | 1408/s | 256h |
| 4 | 14.5s/10k | 2758/s | 130h |
| 6 | 14.6s/10k | 4109/s | 87h |
| 8 | 15s/10k | 5333/s | 65h |
| 12 | 16.1s/10k | 7453/s | 48h |
| 16 | 17.9s/10K | 8888/s | 42h |
| 18 | 19s/10k | 9473/s | 38h |
| 20 | 21.37s/10k | 9358/s | 39h |
+----------+---------------------------------+--------+------------------------------------
core / 1 логический процессор занял почти столько же времени.Как видно, время записи увеличивается линейно с количеством процессов и не зависит от количества ядер и логических процессоров.Максимальное количество операций ввода-вывода в секунду для таблиц Azure составляет около 20 КБ.
Создайте набор из 20 задач в консольном приложении.Это не было оптимальным, и производительность ухудшалась по мере уменьшения количества ядер или увеличения количества потоков.Наилучшая производительность наблюдалась для 2 задач.Я попытался изменить минимальный лимит в threadPool, но это ничего не изменило. ThreadPool.SetMinThreads(20, 20);
Код:
foreach (var index in processIndex)
{
Task t = Task.Run(() =>
{
//gets the appropriate file to read and write to table
string currentFile = string.Format(outFileFormat, index);
Service service = new Service(currentFile);
service.JustReadFile();
});
tasks.Add(t);
}
tasks.WaitAll();
Производительность:
+--------+--------+------------------------------------+
| #tasks | W/s | Total time in hours (1.3b queries) |
+--------+--------+------------------------------------+
| 2 | 1408/s | 256h |
| 16 | ~800/s | ~488h |
| 18 | ~800/s | ~488h |
| 20 | ~800/s | ~488h |
+--------+--------+------------------------------------+
В приведенном выше коде все, что я делаю, - это чтение файла для соответствующей задачи.Каждое задание имеет свой предварительно назначенный файл для чтения.Здесь не происходит запись в лазурную таблицу, и это само по себе отрицательно сказывается на увеличении числа задач.Я подумал, что, возможно, задачи конкурируют за ресурсы или слишком много накладных расходов при переключении контекста.Поскольку каждая задача имеет свой собственный объект Service, я считаю, что это может быть не так.Я также считаю, что чтение файлов и создание объектов - это интенсивная задача ввода-вывода, но если 20 процессов могут справиться с этим, то и 20 задач могут справиться?
Что здесь происходит и как я могу решить эту проблему с помощью потоков / задач?
спасибо!