170 похожих чатов

Просто работа большого количества потоков разве может влиять на производительность

остальных потоков? То есть друг друга.

Если в целом процесс, сумма потоков и 1% мощности еле использует.🤔

64 ответов

18 просмотров

Может. Вы лучше или код покажите, или разбирайтесь почему у вас потоки не нагружены. Просто сделать 1000 потоков не выход - накладные расходы будут бешеные.

Есть например накладные ресурсы, за железку процессорного времени, за синхронизацию, за выделение потоков если ты создаёшь их, и тд

Николай-Threadripper Автор вопроса
SomebodyOdd
Может. Вы лучше или код покажите, или разбирайтесь...

Есть 1500 устройств, нужно каждые несколько сек опрашивать, и ожидать ответа. Сейчас дошло до того, что в каждом потоке сначала идёт Sleep, потом ожидание Slim семафора. Вычисления небольшие, но ожидания долгие. И по ощущениям, это садит другие потоки из Пула. Возможно, по факту сверху приложения есть системный цикл, переключающий все потоки? Но почему это медленно, ведь нагрузки на ЦП нет.🤔

https://ru.bmstu.wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%B0

Николай Threadripper
Есть 1500 устройств, нужно каждые несколько сек оп...

Вы там что, рожаете 1500 потоков? Даже не тасков?

Николай-Threadripper Автор вопроса
SomebodyOdd
Вы там что, рожаете 1500 потоков? Даже не тасков?

Вообще потоков 3000. Но они 1 раз родились, а потом работают. Код похож на while(Active) { Work();//тоже может ждать долго Sleep(1000); }

Николай Threadripper
Вообще потоков 3000. Но они 1 раз родились, а пото...

В идеале - перепишите всё (в том числе этот Work()) на таски. Незачем рожать 3к потоков, чтобы они потом спали, если можно обойтись парочкой, что есть в системном тредпуле

Николай-Threadripper Автор вопроса
SomebodyOdd
В идеале - перепишите всё (в том числе этот Work()...

Но таски либо будут создавать каждый раз кучу новых потоков, что ещё большая нагрузка. Либо будут работать в пуле, а в нём почему то не выделяется более 30 потоков, из-за чего всё приложение зависает. Так как стоит очередь в 3000 запросов.

Николай Threadripper
Но таски либо будут создавать каждый раз кучу новы...

Во первых, размер пул регулируется. Во вторых - вы таки почитайте как это работает. Вы не пробовали, а уже критикуете.

Николай-Threadripper Автор вопроса
SomebodyOdd
Во первых, размер пул регулируется. Во вторых - вы...

Так я с этого уже ушёл. Использовал Threading.Timer. Task.Run тоже использовал.

Николай Threadripper
Так я с этого уже ушёл. Использовал Threading.Time...

Что представляет собой Work? Это IO или вычисления?

Николай-Threadripper Автор вопроса
SomebodyOdd
Что представляет собой Work? Это IO или вычисления...

Это отправка запроса на устройство, и ожидание ответа.

Николай Threadripper
Это отправка запроса на устройство, и ожидание отв...

То есть вы даже не вычисляете потом нчиего по этому ответу? Вам тасков хватит с головой. Только таски должны быть ВЕЗДЕ. Начиная от этого цикла, и заканчивая отправкой/получением ответа от устройства. Почти всё IO в дотнете умеет в таски, всякие SerialPort не исключение

Николай-Threadripper Автор вопроса
SomebodyOdd
То есть вы даже не вычисляете потом нчиего по этом...

Но как Таски это обработают, если по факту нужно обрабатывать одновременно много долгих запросов?

Николай Threadripper
Но как Таски это обработают, если по факту нужно о...

Почитайте документацию, ещё раз. Они просто не будут напрасно держать поток, когда его можно не держать. То есть во время этого слипа, например, таска отпустит поток заниматься другими делами и продолжится позже, по истечению "слипа". И на ожидании ответа от устройства тоже.

Николай-Threadripper Автор вопроса
SomebodyOdd
Почитайте документацию, ещё раз. Они просто не буд...

Попробую изучить🥺 Понимаю что ожиданий не должно быть. Но не знаю как

Николай Threadripper
Попробую изучить🥺 Понимаю что ожиданий не должно б...

Ну вот асинхронное программирование вам ответ. Как раз проблему ожиданий и решает (в том числе)

Николай Threadripper
Да

а что мешает сразу заслать всем команду и ловить ответы и писать их в таблицу по мере ответов id, время, ответ и играйте в эту таблицу как хотите

Николай-Threadripper Автор вопроса
Alex SAS
а что мешает сразу заслать всем команду и ловить о...

Что значит сразу всем? Нужно регулярно, каждые 5 сек повторять команду. Кто будет инициатором этой команды?

Николай Threadripper
Что значит сразу всем? Нужно регулярно, каждые 5 с...

а сейчас кто шлет? тот пусть и шлет раз в 5 сек команду, время отправки есть и 2 поток пусть слушает ответы и пишет время ответа и если на ответ будет уходить более 5 сек то тогда что делаем?

Николай-Threadripper Автор вопроса
Alex SAS
а сейчас кто шлет? тот пусть и шлет раз в 5 сек ко...

Пока ответ не придёт, следующая отправка не начнётся. Период ожидания ждётся после получения ответа. А отправить второй раз, не дождавшись ответа, нельзя.

Николай Threadripper
Пока ответ не придёт, следующая отправка не начнёт...

тогда о каких 5 сек речь? кто то за 1 сек ответил, кто то за 10 и ситуация, что ответ вообще не пришел, то мы его будем ждать вечность? тут или устанавливать период за который будет гарантированный ответ или что мешает 2 и последующие отправки делать только если получен ответ от устройства

Николай-Threadripper Автор вопроса
Alex SAS
тогда о каких 5 сек речь? кто то за 1 сек ответил,...

Так последующие отправки и так идут через 5 сек после получения ответа.

Николай Threadripper
Так последующие отправки и так идут через 5 сек по...

тогда у тебя там полнейший рандом, и 5 сек паузы ни на что не влияют

Николай-Threadripper Автор вопроса
Alex SAS
тогда у тебя там полнейший рандом, и 5 сек паузы н...

Всмысле ни на что? Всмысле, они не должны понижать производительность?

Николай Threadripper
Всмысле ни на что? Всмысле, они не должны понижать...

понизить то чего нет, это фантастика цель иметь срез раз в 5 сек, ответ гарантировано менее 3 сек вариант с тем что ответ не прийдет как реализован?

Николай-Threadripper Автор вопроса
Alex SAS
понизить то чего нет, это фантастика цель иметь с...

У семафора есть Wait(Timeout). Но это не важно ведь. это другой вопрос.

Николай Threadripper
Есть 1500 устройств, нужно каждые несколько сек оп...

Попробуй переделать с sleep на таски и асинхронность, это получится так, что потоки будут брать работу, только тогда, когда есть чем заниматься, и в момент sleep они будут заниматься другими вещами. И может случится так что тебе нужно не 1000 потоков, а 10

Николай-Threadripper Автор вопроса
SomebodyOdd
Ну вот асинхронное программирование вам ответ. Как...

Не знаю почему, но использование тасков Стабильно создаёт Дедлок всего приложения. А если то же самое запускать в отдельных потоках, то всё отлично. Это выглядит ровно так, что создав очередь из ожидающих 10 потоков, он не создаёт новые, а ждёт эти. И так как их 1500*2 сек, получается будет ждать каждого тика около 15 мин... Но почему.... Он же должен создавать сколько угодно новых потоков, если имеющиеся заняты.

Николай-Threadripper Автор вопроса
Николай Threadripper
Не знаю почему, но использование тасков Стабильно ...

Читай документацию: Когда не следует использовать потоки из пула потоков: Имеются задачи, которые приводят к блокировке потока на длительное время. Для пула потоков определено максимальное количество потоков, поэтому большое число заблокированных потоков в пуле может препятствовать запуску задач. Именно это и происходит. Так что всё же Таски это не твой вариант, плохой совет.

Николай Threadripper
Читай документацию: Когда не следует использовать...

Я запутался. Если происходит блокировка потоков ожиданием, то почему таски — это плохой совет? Наоборот же, блокировать потоки — это плохо, поэтому таски — хороший совет.

Николай-Threadripper Автор вопроса
Ilya L
Я запутался. Если происходит блокировка потоков ож...

Так полюбому выполняющаяся задача блокирующая. Состоящая из синхронной отправки и ожидания ответа. И таких задач много...

Николай Threadripper
Так полюбому выполняющаяся задача блокирующая. Сос...

Что значит по-любому? Если она на цпу что-то считает, то да. А если она отправила запрос на диск/сеть и ждёт ответа, то что мешает её сделать асинхронной?

Николай Threadripper
Не знаю почему, но использование тасков Стабильно ...

Код покажите. С высокой вероятностью, вы не поняли суть тасков и у вас где-то .GetResult или .Result вылезает

Николай Threadripper
Читай документацию: Когда не следует использовать...

И этот совет актуален тогда, когда у вас нет контроля над всем кодом в цепочке и у вас нет никакого выхода, кроме как блокировать поток. Но у вас есть контроль, вам не нужно блокироваться на IO

Николай-Threadripper Автор вопроса
SomebodyOdd
Код покажите. С высокой вероятностью, вы не поняли...

Найн, Считайте, что запускается Task.Factory.StartNew(Thread.Sleep(3000)), TaskCreationOptions.LongRunning);

Николай-Threadripper Автор вопроса
Ilya L
И что мешает заменить на Task.Delay(3000)?

А что это изменит? Это для примера, как блокирующая операция. Она может быть любая, как сложное вычисление, так и ожидание большого количества данных от разных микросервисов.

Николай-Threadripper Автор вопроса
Ilya L
Ожидание станет неблокирующим.

То есть метод пойдёт работать дальше?

Николай Threadripper
То есть метод пойдёт работать дальше?

Да, точно так же, как и в случае Task.Factory.StartNew(Thread.Sleep(3000)), TaskCreationOptions.LongRunning); :)

Николай Threadripper
То есть метод пойдёт работать дальше?

Блокирующий IO - это поставить печься пирог, сесть перед печкой и ничего не делать, пока оно не испечется. Асинхронный IO - это поставить печься пирог и уйти заниматься своими делами, пока он не допечется. Делая Sleep или пользуясь чем-то блокирующим не-асинхронным, вы сидите перед печкой и смотрите на пирог. Не надо так так. Пользуйтесь асинхронными версиями с await-ами. Через что общаетесь с устройством? Http/tcp? SerialPort?

Николай-Threadripper Автор вопроса
SomebodyOdd
Блокирующий IO - это поставить печься пирог, сесть...

Через TcpSocket, у себя я использую BeginSend/BeginRead. Но тут такого нет.

Николай Threadripper
Через TcpSocket, у себя я использую BeginSend/Begi...

Метод отправки запроса и получения ответа может, буквально, выглядить вот так await WriteAsync(/*arguments*/); var response = new byte[10000]; await Read(/* arguments */); //Делаем что надо с response

Николай-Threadripper Автор вопроса
SomebodyOdd
Метод отправки запроса и получения ответа может, б...

И пока будет ждаться Await Read, другие потоки будут продолжать работать? Но почему они сейчас не работают?

Николай Threadripper
И пока будет ждаться Await Read, другие потоки буд...

Да. Ещё раз спрошу - вы точно читали доку? Потому что там написано это, и не только

Николай Threadripper
Не знаю почему, но использование тасков Стабильно ...

Так бывает, если у тебя код в тасках очень стрёмный.

Николай Threadripper
Так полюбому выполняющаяся задача блокирующая. Сос...

Необходимо пояснение. Почему это ожидание обязательно блокирующее? Это плохая идея — писать такой код, и писать его на тасках.

Ilya L
Да, точно так же, как и в случае Task.Factory.Star...

Бже какой срам, тебе должно быть стыдно.

Николай-Threadripper Автор вопроса
Dr. Friedrich von Never
Так бывает, если у тебя код в тасках очень стрёмны...

Но в конце его уже не было, блокировки выключил. Выполнялся быстро, но очень много вычислений. И всё равно забивали пул.

Николай-Threadripper Автор вопроса
Dr. Friedrich von Never
Необходимо пояснение. Почему это ожидание обязател...

Даже не блокирующий занимает все Таски... 😔 Либо я что то упускаю.🧐 А вообще, блокировка нужна в том числе для того, что бы новая команда не ушла до возврата предыдущей.

Николай Threadripper
Даже не блокирующий занимает все Таски... 😔 Либо я...

Просто "забей весь пул", а потом посмотри стеки потоков в нём, и будет видно, в чём проблема.

Николай-Threadripper Автор вопроса
Dr. Friedrich von Never
Просто "забей весь пул", а потом посмотри стеки по...

А как смотреть стеки потоков? Просто через просмотр потоков?🥺 Где показаны имена и состояние. Тут основная проблема, что логика была написана не мной, раньше вообще по 2 потока и таймеру создавалось для каждого устройства. Но их стало очень много. Теперь я унизил до 2 потоков на все устройства, и работу действий в пуле. Он постоянно создаёт и убивает потоки, а не использует одни и те же. Что всё же не достаточно эффективно.

Николай Threadripper
А как смотреть стеки потоков? Просто через просмо...

Как смотреть стеки потоков? Через просмотр потоков. А как реализовать просмотр потоков? Глядя на стеки потоков!

Ilya L
Отказываюсь.

Стыдиться или от того что написал?)

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
в JclConsole объявлено так: function CtrlHandler(CtrlType: DWORD): BOOL; stdcall; - где ваше объявление с stdcall? у вас на картинке нет stdcall
Karagy
8
Ребят в СИ можно реализовать ООП?
Николай
33
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта