Ответы пользователя по тегу Многопоточность
  • Как сделать многопоточный чат?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    у вас должен быть один основной поток, где вы ожидаете подключения. При подключении у вас создается сокет, который вы кидаете в отдельный тред.

    Socket clientSocket = serverSocket.accept();

    То есть у вас не верно логика работы построена. Вы при получении соединения начинаете сразу же с ним работтать, а вам нужно в цикле слушать новые соединения и для каждого запускать тред.

    Хочу отдельно отметить, что при увеличении количества потоков производительность будет падать. При достижении отметки в пару сотен клиентов например. В этом случае лучше переключаться на event loop/микротреды/корутины.
    Ответ написан
    1 комментарий
  • Спасет ли меня многопоточность?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    много потоков это хорошо, но с ростом количества потоков производительность будет падать ну то есть 8 потоков будут работать не в два раза быстрее чем 4.

    У вас по сути большая часть времени - это работа с сетью, что медленно. Выход - event loop. В рамках одного потока запускаем много много неблокируемых запроса, и по мере завершения запросов обрабатываем результат.

    Комбинация нескольких потоков (по количеству ядер процессора) и event loop даст максимальную утилизацию процессора.
    Ответ написан
    5 комментариев
  • Что такое тяжелая и легкая задача для потока?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    когда выполняется какой тред разруливается системным планировщиком задач, файберы же это реализация кооперативной многозадачности (то есть в рамках одного треда может работать только один файбер и они постоянно переключаются давай друг дружке чуть чуть поработать).

    Для начала разберитесь в реализации и различиях между процессами, потоками и файберами, и тогда большая часть ваших вопросов улетучатся. Например можно начать с вики
    Ответ написан
  • Как один сетевой сокет обрабатывает много соединений?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Сокет != порт
    Ответ написан
    Комментировать
  • Эмулирование многопоточности в php?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    pthread еще.

    В целом же вам нужно пересмотреть архитектуру парсеров, что бы можно было организовать очередь на скачивание и обработчик результата и тогда можно было бы использовать мультикурл - это было бы самым эффективным способом.
    Ответ написан
  • Как правильно считать время выполнения многопоточного алгоритма?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Ну вы же не думаете что все 4 процесса работают постоянно? Если вы запустите ваше приложение с повышенным приоритетом процессора теоритически разница будет уже чуть меньше. Но все упирается в то сколько ядер процессора вам доступно. Так же не забывайте - не вы один на всем компьютере занимаете процессорное время.
    Ответ написан
    Комментировать
  • Как правильно реализовать сервер для игры?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Правильно ли ответить и закрыть подключение

    ну как, если вам это соединение больше не понадобится, то да. Если люди будут соединяться раз в 10 секунд и их будет много, у вас просто упадет сервер (ну или просто нагрузка будет нереально большой). Накладные расходы на создание соединения выше, чем оные на обслуживание.

    Как только соединение создано, оно только занимает один дискриптор сокета. И все. У вас могут просто сокеты закончиться свободные, но это решаемая проблема. И все. Больше ресурсов оно не потребляет. А при помощи epoll можно выбирать соединения из общей пачки которые содержат данные на чтение или запись, или которые отвалились... правда я не уверен в контексте libevent, мне казалось что оно это само разруливает.

    Так же можно сделать один поток, который принимает соединения и раскидывает их по процессам воркерам. А те уже их обслуживают. Например в nginx каждый процесс-воркер обслуживает свои пачки соединений и разруливает все внутри процесса через тот же epoll. То есть не соединение = процесс, а много соединений = процесс.
    Ответ написан
    Комментировать
  • Асинхронная многопоточность в PHP: для чего?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Все очень просто. Вот вам приблизительное значение таймингов доступа к данным:
    io-cost.png

    То есть запросив данные в сети мы тупо ждем. Долго ждем и ничего не делаем.

    В случае с curl (он же HTTP) мы можем соорудить очередь запросов и послать их одним махом и ждать пока завершится загрузка всех документов в очереди для обработки результатов. Если мы хотим забрать 10 документов, то без multi curl у нас ушло бы времени "среднее время получения документа" * 10. И это примерно. В случае же с мультикурлом мы получаем время обработки 10 запросов как время выполнения самого долгого запроса. Если представить что время запросов всегда одинаковое, получаем выйгрыш примерно в 10 раз.

    С сокетами веселее. Они бывают блокируемые (по умолчанию) и неблокируемые (выставляется опцией O_NONBLOCK). Для начала давайте определимся что такое чтение данных из сокетов и как нам это дело предоставляет операционная система. Упрощенно, когда мы создаем сокет, мы просто просим операционную систему предоставить оный. У каждого сокета есть буфер чтения и буфер записи. Если буфер записи полный - ОС начинает отправку данных пока буфер не опустеет (буфер записи нужен для организации проверки дошли ли пакеты и переотправки в случае чего, так же этот буфер замешан в выборе операционкой размеров пакетов и т.д. Это не особо важно в контексте вопроса). Когда данные приходят в сокет, сначала они помещаются в буфер чтения. Там они лежат пока их не попросят вернуть из кода. Так мы можем быть уверены в том, что данные не пропадут.

    Так вот... возьмем блокирующие сокеты и попробуем запросить 1024 байт данных из оного. Причем клиент в данный момент ничего не отправляет, буфер чтения пустой. И так допустим минут 10. Как только мы сделали запрос за данными, и оказалось что буфер чтения пустой, процесс выполнения блокируется пока не появятся данные.

    А теперь представим что проверять периодически наличие данных нам надо не в одном сокете а в десятке. Представим так же что 9 клиентов подключенных по нашим сокетам хорошие и присылают данные вовремя, а один не хороший и любит тупить по пол часа. Если бы мы пользовались блокирующими сокетами, то мы можем обрабатывать только одного клиента за раз. Причем если у него вдруг данных не оказалось - нам придется ждать, хотя в других сокетах уже вполне могли появиться данные какие для обработки. И если в случае с "хорошими" клиентами мы можем тратить на оных по пол секунды - секундочке, то наткнувшись на плохого клиента наш сервер замирает за те самые пол часа о которых мы договаривались. Сервер тупо ждет "плохого" клиента а хорошие в итоге не могут достучаться до сервера. Новых соединений мы так же не установим... короче все мертво.

    И тут на помощ к нам приходит опция O_NONBLOCK. В этом случае если у сокета пустой буфер чтения он сразу вернет выполнение не вернув нам ни капли данных не дожидаясь медлительных клиентов-тугодумов. В случае если буфер не пустой - все будет так же как и в случае с блокирующими сокетами - тупо вернет содержимое буфера и вернет управление. Так что мы можем в бесконечном цикле просто проверять по очереди все сокеты. В этом случае делей получения данных будет сведен к минимуму.

    И вроде как все хорошо, да только бесконечный луп без блокировок это полная загрузка процессора. Не хорошо. При блокирующих вызовах нагрузка не большея (зависит от задачи) но тогда наш сервер очень медленно будет отвечать. Но не все так плохо.

    Еще есть такая чудная штука, которую предоставляет операционная система как select или epol (в контексте php socket_select и stream_select). Данные функции позволяют нам скармливать массивы сокетов, за которыми вы следите (не сокетов, а их дескрипторов но не суть, и не один массив а три, массив дескрипторов что бы следить появились ли данные на чтение, записал ли сокет все и освободился ли буфер записи и третий отслеживает сокеты в которых произошли какие-то ошибки, например отвалилось соединение). Так же этой функции можно задавать таймаут, что очень удобно если мы сначала собираем данные с нескольких клиентов и если от них небыло вестей пару секунд, значит мы забрали все и можно начинать обработку.

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

    Но все что выше имеет смысл только с TCP/TLS, если бы у нас были UDP сокеты, то было бы еще веселее. Там нету никаких буферов. Не принял данные - потерял данные. Нету соединений. Нету блокировок. Есть только пакеты. Поэтому этот протокол используют (или используют как основу) для реализации реалтайм систем. Задержек нету, а если какой пает не дошел, велика вероятность что он уже не актуален. Правда если сеть не надежная и потери пакетов велики, то начинается боль и слезы и обычно все же для таких случаев дублируют все на TCP.
    Ответ написан
  • Ruby: существует ли блокировка ресурса в потоке при записи?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    не понятно чем вам не угадили стандартные мютексы. Потоки ж будут блокироваться только при попытке захватить власть, когда им этого не положено. То есть только при записи. При чтении блокировать если нужно, что бы у потоков всегда были актуальные данные - тогда семафоры.

    А так вот довольно интересное решение основанное на атомарных операциях.
    Ответ написан
  • Как на C# реализовать многопоточное управление MySQL?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Организуйте пулл соединений, очередь запросов и разруливайте.
    Ответ написан
  • Как запустить несколько потоков одновременно в c#?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    ThreadPool не подойдет?
    Ответ написан
    Комментировать
  • (C++) Клиент-Серверное взаимодействие. Многопоточность. Когда? Как?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    1. Отрисовку точно стоит вынести в отдельный от чтения данных поток

    2. По поводу бесконечного цикла - именно так. При вызове recvfrom у вас будет блокирован ваш поток пока не придут данные, так что ничего страшного от использования бесконечного цикла у вас не будет. Именно по этому и нужно выносить это все дело в отдельный процесс/поток.

    3. Кросплатформенная разработка в вижле? Увы нет, во всяком случае насколько я знаю. Почитайте про cmake и просто make (cmake плохо дружит с вижлой, иногда бывают проблемы и после генерации проекта приходится тратить время еще на настройку, так что чаще проще уж один раз настроить и таскать с собой настройки проекта).
    Вообще тут проще побродить по опенсорсным проектам кросплатформенным и посмотреть как там все это дело реализованно.

    3.5. ну тут все просто. в linux POSIX, в windows - WinApi (или WinRT если вам хватит поддержки win8+). То есть скажем... код сервера работающий с сокетами у вас под эти две платформы будет различаться на 90% так как все завязано на системное api. То есть вам нужно сделать какую-то прослойку инкапсулирующую сетевую часть, и уже ее реализацию подменять при сборке под конкретную платформу. Либо взять готовое решение для этой прослойки. А вот при реализации бизнес-логики различия между платформами зависят только от самой логики.
    Ответ написан
  • Как наиболее эффективно выкачать несколько миллионов html страниц, при этом не потратив вечность?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    У вас что 1400 потоков создается? Если у вас оперативки гигов 8-16 то конечно не хватит памяти... Вы хоть память освобождаете?

    Вам нужно написать менеджер очереди. Несколько потоков будут висеть постоянно и каждый будет обращаться за новым заданием к менеджеру (придется блокировать остальные потоки дабы небыло гонки за ресурсами). Получив задание ваш поток-воркер выкачает данные и сохранит результат работы в базу/файловую систему и будет просить новое задание...
    Ответ написан
    2 комментария