Рубрика «concurrency» - 6

Когда мы начали рассказывать про свой OpenSource акторный фреймворк для C++ на Хабре, мы пообещали описывать некоторые особенности деталей реализации SObjectizer-а. Одна из новых фич, которая была реализована в недавно вышедшей версии 5.5.19, отлично подходит для такого рассказа. Кроме того, она интересна еще и тем, что нам пришлось взглянуть на сценарии использования SObjectizer с совершенно другой стороны. Можно даже сказать, что один из наших шаблонов оказался разорванным.

Речь идет о возможности SObjectizer-а выполнять все свои действия на одной единственной рабочей нити. Начиная с версии 5.5.19 использовать Actor- и Publish/Subscribe модели можно даже в однопоточном приложении. Понятное дело, что акторы должны будут работать в режиме кооперативной многозадачности, но в каких-то случаях именно это и требуется.

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

Читать полностью »

image

В этих 3-ех статьях я детально расскажу об атомарных операциях, барьерах памяти и о быстром обмене данными между потоками, а так же о «sequence-points» на примере «execute-around-idiom», а заодно постараемся вместе сделать что-нибудь полезное — умный указатель, который делает любой объект потоко-безопасным для любых операций с его членами переменными или функциями. А затем покажем как используя его достичь производительности высоко-оптимизированных lock-free алгоритмов на 8 — 64 ядрах.
Читать полностью »

Основной принцип программирования гласит: не изобретать велосипед. Но иногда, чтобы понять, что происходит и как использовать инструмент правильно, нам необходимо это делать. Сегодня изобретаем ConcrurrentHashMap.

Сперва нам понадобятся 2 вещи. Начнем с 2х тестов — первый скажет, что у нашей реализации нет data races (на самом деле нам нужно проверить, правилен ли наш тест также путем тестирования заведомо некорректной реализации), второй тест мы будем использовать для тестирования производительности с точки зрения throughput.

Читать полностью »

Завершаем рассказ, начатый в первой части. Сегодня рассмотрим еще несколько граблей, на которые довелось наступить за годы использования SObjectizer-а в повседневной работе.

Продолжаем перечислять грабли

Народ хочет синхронности...

Акторы в Модели Акторов и агенты у нас в SObjectizer общаются посредством асинхронных сообщений. И в этом кроется одна из причин привлекательности Модели Акторов для некоторых типов задач. Казалось бы, асинхронность — это один из краеугольных камней, один из бонусов, поэтому пользуйся себе на здоровье и получай удовольствие.

Ан нет. На практике быстро начались просьбы сделать в SObjectizer возможность синхронного взаимодействия агентов. Очень долго я этим просьбам сопротивлялся. Но в конце-концов сдался. Пришлось добавить в SObjectizer возможность выполнить синхронный запрос от одного агента к другому.

Выглядит в коде это вот так:

Читать полностью »

Данная статья является первой частью текстовой версии одноименного доклада с февральской конференции C++ CoreHard Winter 2017. Так уж получилось, что вот уже 15 лет я отвечаю за разработку фреймворка SObjectizer. Это один из тех немногих все еще живых и все еще развивающихся OpenSource фреймворков для C++, которые позволяют использовать Модель Акторов. Соответственно, за это время неоднократно доводилось попробовать Модель Акторов в деле, в результате чего накопился некоторый опыт. В основном это был положительный опыт, но есть и некоторые неочевидные моменты, про которые было бы хорошо узнать заранее. О том, на какие грабли довелось наступить, какие шишки были набиты, как можно упростить себе жизнь и как это сказалось на развитии SObjectizer-а и пойдет речь далее.

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

Читать полностью »

Данная статья является доработанной текстовой версией одноименного доклада с конференции C++ CoreHard Autumn 2016, которая проходила в Минске в октябре прошлого года. Желание сделать эту статью возникло под впечатлением о том, что в мире C++ разработчики как бы делятся на два больших и не пересекающихся лагеря. В первом лагере находятся матерые спецы, которые все видели, все знают и все умеют, за плечами у которых десятки собственноручно написанных реализаций Модели Акторов, внутрях у которых хитрые, конечно же самостоятельно сделанные, lock-free очереди и state-of-the-art механизмы обслуживания сообщений. Такие проффи сами часами могут рассказывать про тонкости многопоточного программирования (только почему-то редко это делают). Во втором лагере — зеленые новички, которых волею судьбы занесло в мир C++, которые пока слабо представляют себе различия между unique_ptr и shared_ptr, про шаблоны только слышали, а в области многопоточности имеют поверхностное впечатление только о std::thread, std::mutex и, может быть, std::condition_variable. Для людей из первого лагеря я вряд ли что-нибудь интересное расскажу, а вот разработчикам из второго лагеря попробую вкратце рассказать о том, что Модель Акторов в C++ — это нормально. И что есть ряд готовых инструментов, на примере которых можно увидеть, что же это такое.

Читать полностью »

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

В небольшом однопоточном приложении довольно просто: можно прервать всю работу и рестартовать. Это один из факторов, благодаря которому Erlang снискал себе заслуженную популярность, ведь идеология fail fast является одним из краеугольных камней Erlang-а с его легковесными процессами. Если же приложение большое, сложное и многопоточное, то не разумно рестартовать все приложение, если лишь одна из его нитей столкнулась с проблемами. Еще хуже в ситуации с реализациями Модели Акторов, в которых сотни тысяч акторов могут работать на десятках рабочих нитей. Проблема одного актора вряд ли должна сказываться на всех остальных акторах.

В данной статье мы расскажем, как мы подошли к обработке ошибок в своем фреймворке SObjectizer.

Исключениям – да, кодам возврата – нет!

Когда SObjectizer-4 появился в 2002-ом году, мы сделали большую ошибку – предпочли использовать коды возврата исключениям. И весь последующий опыт разработки на SObjectizer-4 снова и снова убеждал в одной простой истине: если ошибка может быть прогнорирована разработчиком, то она будет им проигнорирована. Поэтому при создании SObjectizer-5 мы решили использовать исключения для информирования об ошибках.

Читать полностью »

В предыдущих статьях мы несколько раз упоминали о такой проблеме, как перегрузка агентов. Что это такое? Чем это грозит? Как с этим бороться? Обо всем этом мы и поговорим сегодня.

Проблема перегрузки агентов возникает, когда какому-то агенту отсылается больше сообщений, чем он успевает обрабатывать. В результате очереди сообщений постоянно увеличиваются в размерах. Растущие очереди расходуют память. Расход памяти ведет к замедлению работы приложения. Из-за замедления проблемный агент начинает обрабатывать сообщения дольше, что увеличивает скорость роста очередей сообщений. Что способствует более быстрому расходу памяти. Что ведет к еще большему замедлению приложения. Что ведет к еще более медленной работе проблемного агента… Как итог, приложение медленно и печально деградирует до полной неработоспособности.

Проблема усугубляется еще и тем, что взаимодействие посредством асинхронных сообщений и использование подхода fire-and-forget прямо таки провоцирует возникновение перегрузок (fire-and-forget – это когда агент A получает входящее сообщение M1, выполняет его обработку и отсылает исходящее сообщение M2 агенту B не заботясь о последствиях).

Читать полностью »

Познакомив читателей с фреймворком SObjectizer, его возможностями и особенностями, можно перейти к рассказу о некоторых уроках, которые нам довелось усвоить за более чем четырнадцать лет использования SObjectizer-а в разработке C++ного софта. Сегодня поговорим о том, когда агенты в виде конечных автоматов не являются хорошим выбором, а когда являются. О том, что возможность создания большого количества агентов – это не столько решение, сколько сама по себе проблема. И о том, как первое соотносится со вторым...

Читать полностью »

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

Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js