|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Petro123, Ну короче сейчас все сделано через T-SQL процедуру. Извлекаются данные курсором и потом идет длинный алгоритм со сложной логикой со считыванием данных из других таблиц и последущими расчетами. По каждому элементу отдельно. Получается обрабатывать около 20-30 элементов в секунду. Нужно существенно увеличить эту цифру. Т.к. нужно обрабатывать архивы данных. Что я хочу сделать через перевод на C# и увеличение количества потоков, выполняющих данный алгоритм, что выльется в некую цепочку: CpuBound(мелкая обработка)+IOBound(долго)+CpuBound(мелкая обработка)+IOBound(долго)+IOBound(долго)+CpuBound(мелкая обработка). ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 10:44 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreИзвлекаются данные курсором и потом идет длинный алгоритм со сложной логикой со считыванием данных из других таблиц и последущими расчетами. Курсоры в T-SQL = тормоза. Это было подтверждено уже не раз. И способ убыстрения таких алгоритмов, как ни странно - отказ от курсоров (и скалярных UDF). Все расчеты и извлечение данных помещаются в один запрос. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 10:49 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
А тему я создал потому, что хотел понять есть ли стандартные способы от разработчиков C#. Странно стало, что PLinq и Parallel не умеют по async. Думал может чего упустил, но получается не упустил. Ну, придется воспользоватся велосипедом ForEachAsyncConcurrent, только я думаю там имеет смысл добавить ThreadPool.SetMaxThreads если maxDegreeOfParallelism задан больше Environment.ProcessorCount, что не учтено в данном методе. Иначе толку от maxDegreeOfParallelism не будет - пул потоков тупо не запустит новые задачи. Вот поэтому я и не хотел использовать велосипеды, уж разрабы C# точно не упустят важные вещи. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 10:51 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Сон Веры ПавловныWaspNewCoreИзвлекаются данные курсором и потом идет длинный алгоритм со сложной логикой со считыванием данных из других таблиц и последущими расчетами. Курсоры в T-SQL = тормоза. Это было подтверждено уже не раз. И способ убыстрения таких алгоритмов, как ни странно - отказ от курсоров (и скалярных UDF). Все расчеты и извлечение данных помещаются в один запрос. Ну а как без алгоритмов то, в условиях когда есть алгоритмы вида if сделай то-то, else сделай длинную цепочку другого алгоритма. Упихивать это в чистый SQL слишком сложно и запутанно - через всякий там merge и прочие. Ну вот думаю проще перенести логику на C# хотя бы. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 10:53 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreНу а как без алгоритмов то, в условиях когда есть алгоритмы вида if сделай то-то, else сделай длинную цепочку другого алгоритма. Упихивать это в чистый SQL слишком сложно и запутанно - через всякий там merge и прочие. Вполне нормально. Декомпозиция решает. Сложные/громоздкие вычисления выносятся в инлайновые TVF, и используются в основном запросе посредством cross/outer apply. Поскольку функции инлайновые, то оптимизатором всё это будет собрано в один запрос с единым планом выполнения. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:01 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreСон Веры Павловныпропущено... Курсоры в T-SQL = тормоза. Это было подтверждено уже не раз. И способ убыстрения таких алгоритмов, как ни странно - отказ от курсоров (и скалярных UDF). Все расчеты и извлечение данных помещаются в один запрос. Ну а как без алгоритмов то, в условиях когда есть алгоритмы вида if сделай то-то, else сделай длинную цепочку другого алгоритма. Упихивать это в чистый SQL слишком сложно и запутанно - через всякий там merge и прочие. Ну вот думаю проще перенести логику на C# хотя бы. Да запросто - от CASE в качестве полей выбора, до UNION нескольких наборов, удовлетворяющих разным условиям. Настоятельно рекомендую Вам об этом подумать ... ну или назовите приложение, над которым работаете, - чтобы нечаянно с ним не познакомиться ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:01 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
мне проще на C#. тут видимо вопрос опыта в конкретных тенологиях. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:03 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreмне проще на C#. тут видимо вопрос опыта в конкретных тенологиях.именно батенька. Вопрос где размещать БЛ бизнес логику. Он флеймовый. Можно в бд на его ЯП. Можно в АппСервере. Ты выбрал второе т.к. больше знаешь шарп. Логично). ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:11 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Сон Веры ПавловныПоскольку функции инлайновые, то оптимизатором всё это будет собрано в один запрос с единым планом выполнения.в этом я не силен. Я либо оптимизатор бд и его большая хранимка. Либо ОРМ и тогда оптимизатор голова разработчика). Конечно, при аналитике как бы и ОРМ уже не подходит. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:14 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreТ.к. нужно обрабатывать архивы данных.сделайте для архива денормализацию и olap\oltp. Обычно архивы для ускорения как раз отдельно. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:18 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Здесь есть еще один нюанс: когда данные собираются единым запросом, сервер сам обеспечивает консистентность этих данных (либо механизмом блокировок, либо механизмом IRCS). Если зависящие друг от друга данные собираются кучей атомарных запросов в параллельных потоках (и сессиях), есть достаточно неплохой шанс смоделировать ситуацию грязного чтения. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:22 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreчто выльется в некую цепочку:при увлечении цепочками будут потери при переключении контекста. Со школы известно что 2 потока не быстрее в 2 раза одного. А например, денормализация ускорит вам в 10 раз. IMHO ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:24 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Сон Веры Павловныгрязного чтения.ну, у него архив вроде. Данные статичны. Но конечно, один запрос без курсоров это идеал. Это обычно в ветке БД пробуют написать. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:27 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Petro123WaspNewCoreчто выльется в некую цепочку:при увлечении цепочками будут потери при переключении контекста. Со школы известно что 2 потока не быстрее в 2 раза одного. А например, денормализация ускорит вам в 10 раз. IMHO Petro123Сон Веры Павловныгрязного чтения.ну, у него архив вроде. Данные статичны. Но конечно, один запрос без курсоров это идеал. Это обычно в ветке БД пробуют написать. Написать такую сложную логику для меня будет сложновато. Тем более с OLTP и пр. Мне проще перенести на C#. Понятно, что параллельность не увеличит производительность прям ровно в нужное количество потоков, см. Закон Амдала . Но я думаю увеличение будет достаточно существенным. Раз этак в 1.87 с двух потоков и т.д. Со 100 потоков может выжмется ускорение раз в 70. Полагаю для моей текущей задачи такой производительности хватит за глаза. Если потом упрусь в потолок и его все равно будет не хватать (а это вряд ли произойдет в ближайшие годы) подключу спеца по SQL, чтобы он уже ворочал OLPT и пр. Но это слишком далекие планы. Что касается грязного чтения.. хм. Вряд ли. Работа идет с уже готовыми статичными данными. Берется родительская запись и ее обрабатывает один поток. Который запрашивает подчиненные сущности и их обрабатывает, с последующей заливкой в другие таблицы. Пересечений и дедлоков в принципе не должно быть. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:45 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
Или это не Закон Амдала утверждает, что накладные расходы при распараллеливании вычислений уменьшают общую производительность. Забыл, не важно в общем ) ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 11:49 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCore Берется родительская запись и ее обрабатывает один поток. Который запрашивает подчиненные сущности и их обрабатывает, с последующей заливкой в другие таблицы. Пересечений и дедлоков в принципе не должно быть. Ну тут прямо напрашивается select->insert. без всяких await/async ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 12:12 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreСо 100 потоков может выжмется ускорение раз в 70.сомневаюсь. По правилом нужна демка ПРОТОТИП. Ставьте sleep() вместо БЛ и уже завтра, в выходной отпишитсь во сколько раз 20 потоков SELECT record быстрее чем курсор в базе. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 12:51 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
ЕвгенийВWaspNewCore Берется родительская запись и ее обрабатывает один поток. Который запрашивает подчиненные сущности и их обрабатывает, с последующей заливкой в другие таблицы. Пересечений и дедлоков в принципе не должно быть. Ну тут прямо напрашивается select->insert. без всяких await/asyncон хочет 100 select по одной записи одновременно в базу. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2018, 12:52 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreСтранно стало, что PLinq и Parallel не умеют по async. Видимо, научить непросто. Представьте, к очереди элементов еще первоначально не опоточенных, добавится очередь готовых к продолжению после await. Части (или всем) из этих последних нужно продолжить в первоначальном потоке. А еще бывают и такие асинхи , которые не умеют продолжать в чужом потоке (несмотря на ConfigureAwait(false)). ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2018, 11:27 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
LR Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.
Кстати, по поводу этой реализации, которая встречается множество раз (автор знатно постарался в распространении своего говнокода), должен сказать. Не нужно использовать эту реализацию у себя, так как при достаточно большом количестве элементов тупо пожирает память и выход может быть более медленным, чем хотелось бы. В общем, не нужно бездумно копировать всякую дичь со стеков :) ... |
|||
:
Нравится:
Не нравится:
|
|||
19.08.2018, 01:02 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
hVosttНе нужно использовать эту реализацию у себя, так как при достаточно большом количестве элементов тупо пожирает память и выход может быть более медленным, чем хотелось бы. А можете объяснить в чем проблемы ? Я не вижу критичных, метод выглядит вполне юзабельным. А значит я чего-то не понимаю в async/await. Нужно срочно это исправить, просвятите :) И что значит "выход может быть более медленным" ? Какого порядка цифры ? Если речь о лишних микросекундах из-за ожиданий await semaphoreSlim.WaitAsync() то не вижу тут проблем, потери в десяток микросекунд я не считаю - такой сверхоптимизации мне не требуется. У меня всего лишь пара мелких замечаний: 1. добавить ConfigureAwait(false) везде. 2. Код: c# 1.
Начиная с 4.5 фреймворка уже не нужно преобразовывать в массив. WhenAll с тех пор принимает IEnumerable. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.08.2018, 11:43 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCore, Проблема здесь: LR Код: c# 1.
Если через аргумент функции enumerable будет прокачано миллиард элементов, в памяти останутся миллиард экземпляров Task, да и эвейтить этот миллиард то ещё удовольствие. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.08.2018, 11:59 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
hVostt, Да, я думал на этот момент. Но это стандартная проблема с кодом вообще - не создать случайно List на триллиард записей. Полагаю, что проблема как раз из-за необходимости передать в Task.WhenAll массив. Можно немного оптимизировать - заменить Код: c# 1.
на Код: c# 1.
- заменить Код: c# 1.
на Код: c# 1.
не смотрел код Task.WhenAll, но если там что-то типа Код: c# 1. 2.
то должно работать гладко. Но в принципе на не очень больших коллекциях ( ну чтобы не растить List до миллиардов) и так будет работать. В принципе конкретно в своем решении я разбиваю работы на пакеты по ~1000 элементов, так, что особых рисков не будет. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.08.2018, 12:14 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreМожно немного оптимизировать ...или взять правильный, корректно работающий код без блокирующих коллекций https://docs.microsoft.com/ru-ru/dotnet/standard/asynchronous-programming-patterns/consuming-the-task-based-asynchronous-pattern#throttling :) не думаю, что BlockingCollection в контексте отсутствия параллелизма, а это именно так на таск эвейте, хорошая идея, скорее очень плохая. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.08.2018, 13:48 |
|
Как делать кучу параллельных IO-Bound операций ?
|
|||
---|---|---|---|
#18+
WaspNewCoreНо в принципе на не очень больших коллекциях ( ну чтобы не растить List до миллиардов) и так будет работать. В принципе конкретно в своем решении я разбиваю работы на пакеты по ~1000 элементов, так, что особых рисков не будет. Это заряженное ружьишко, которое может очень больно может садануть и прострелить ногу. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.08.2018, 13:48 |
|
|
start [/forum/topic.php?fid=20&msg=39689340&tid=1399268]: |
0ms |
get settings: |
9ms |
get forum list: |
10ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
146ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
54ms |
get tp. blocked users: |
1ms |
others: | 292ms |
total: | 530ms |
0 / 0 |