Рубрика «multithreading»

Привет всем!

Сегодня мы хотели бы в очередной раз затронуть тему одновременного и последовательного выполнения в различных программах, особенно — в распределенных системах. Еще в сентябре мы публиковали статью "Синхронность — это миф" на эту тему, а теперь публикуем перевод более серьезного исследования, которое, надеемся, поможет вам лучше сориентироваться с распределенными системами.
Читать полностью »

Делаем Shrimp еще полезнее: добавляем перекодирование картинок в другие форматы - 1

С начала 2017-го года наша небольшая команда разрабатывает OpenSource-библиотеку RESTinio для встраивания HTTP-сервера в C++ приложения. К своему большому удивлению мы время от времени получаем вопросы из категории «А для чего может потребоваться встраиваемый HTTP-сервер на C++?» К сожалению, на простые вопросы отвечать сложнее всего. Иногда лучшим ответом является пример кода.

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

Этот демо-проект хорош тем, что в нем, во-первых, требуется интеграция с давным-давно написанным и исправно работающим кодом на C или C++ (в данном случае это ImageMagick). Поэтому должно быть понятно, почему имеет смысл встраивать HTTP-сервер в C++ приложение.

И, во-вторых, в данном случае требуется асинхронная обработка запросов, дабы HTTP-сервер не блокировался пока выполняется масштабирование картинки (а это может занимать сотни миллисекунд или даже секунды). А разработку RESTinio мы затеяли именно потому, что не смогли найти вменяемый C++ный встраиваемый сервер, ориентированный именно на асинхронную обработку запросов.

Работу на Shrimp-ом мы построили итеративным путем: сперва была сделана и описана самая простая версия, которая только масштабировала картинки. Затем мы устранили ряд недочетов первой версии и описали это во второй статье. Наконец дошли руки расширить функциональность Shrimp-а еще раз: добавилось преобразование картинок из одного формата в другой. О том, как это было сделано и пойдет речь в данной статье.
Читать полностью »

Ну или почти вся...

Вся правда о linux epoll - 1

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

В статье я постараюсь раскрыть то, что является фундаментальным отличием epoll от других механизмов, то что делает его уникальным, а так же привести статьи, которые просто необходимо прочитать для более глубокого осмысления возможностей и проблем epoll.

Anyone can wield an axe, but it takes a true warrior to make it sing melees melody.

Я предполагаю, что читатель знаком с epoll, по крайней мере прочел страницу man. О epoll, poll, select написано достаточно много, чтобы каждый кто разрабатывал под Linux, хоть раз о нем слышал.

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

Shrimp: масштабируем и раздаем по HTTP картинки на современном C++ посредством ImageMagic++, SObjectizer и RESTinio - 1

Предисловие

Наша небольшая команда занимается развитием двух OpenSource инструментов для C++разработчиков — акторного фреймворка SObjectizer и встраиваемого HTTP-сервера RESTinio. При этом мы регулярно сталкиваемся с парой нетривиальных вопросов:

  • какие фичи добавлять в библиотеку, а какие оставлять «за бортом»?
  • как наглядно показывать «идеологически правильные» способы использования библиотеки?

Хорошо, когда ответы на такие вопросы появляются по ходу использования наших разработок в реальных проектах, когда разработчики приходят к нам со своими жалобами или хотелками. За счет удовлетворения хотелок пользователей мы наполняем свои инструменты функциональностью, которая продиктована самой жизнью, а не «высосана из пальца».

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

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

Сегодня мы хотим рассказать как раз об одной такой «небольшой» задачке, в которой естественным образом объединились SObjectizer и RESTinio.

Масштабирование и раздача картинок. Почему именно это?

В качестве небольшой демо-задачи для самих себя мы выбрали HTTP-сервер, который раздает по запросам отмасштабированные картинки. Вы складываете изображения в какой-то каталог, запускаете HTTP-сервер, делаете к нему запрос вида:
Читать полностью »

Доброго времени суток

Играем с потоками в Node.JS 10.5.0 - 1
У меня на работе возник спор между мной и дотнетчиками насчет потоков в новой версии Node.JS и необходимости их синхронизоровать. Для начала решили выбрать задачу о параллельной записи строк в файл. Тема с worker_threads горячая, прошу под кат.
Читать полностью »

Разработка многопоточного кода — это сложное занятие. Действительно сложное. К счастью для упрощения жизни разработчиков давным-давно придуманы высокоуровневые абстракции, например, task-based parallelism, map-reduce/fork-join, CSP, actors и т.д.

Но когда попадаешь на профильные форумы, где общаются C++ники, то складывается ощущение, что многие просто не в курсе наличия чего-то более простого и удобного, чем std::thread в купе с std::mutex+std::condition_variable. Регулярно встречаются вопросы из категории: «Мне нужно запустить несколько рабочих потоков, в одном делается то-то, во втором то-то, а в третьем то-то. Я их запускаю вот так, а информацией между потоками обмениваюсь вот так. Правильно ли я делаю?»

Очевидно, что такие вопросы задают новички. Но, во-первых, количество неопытной молодежи в разработке софта всегда было велико, и с ростом привлекательности отрасли ИТ это количество только увеличивается. При этом печально, что новички знают про std::thread и std::mutex, но не знают про готовые инструменты, которые могли бы упростить им жизнь (вроде Intel TBB, HPX, QP/C++, Boost.Fiber, FastFlow, CAF, SObjectizer и т.д.).

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

Все это наводит на мысль о том, что имеет смысл на простых примерах показывать, как конкретный фреймворк может помочь в решении даже небольших и, казалось бы, несложных задач, связанных с многопоточностью. Поскольку мы развиваем SObjectizer как раз как инструмент для упрощения разработки многопоточных приложений на C++, то сегодня попробуем показать, как реализованные в SObjectizer-е CSP-шные каналы способны избавить разработчика от части головной боли при написании многопоточного кода.
Читать полностью »

О чем эта статья?

Одной из основных отличительных черт C++ного фреймворка SObjectizer является наличие диспетчеров. Диспетчеры определяют где и как акторы (агенты в терминологии SObjectizer-а) будут обрабатывать свои события: на отдельной нити, на пуле рабочих нитей, на одной общей для группы акторов нити и т.д.

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

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

Преамбула

Недавно один из пользователей SObjectizer-а рассказал про специфическую проблему, с которой ему довелось столкнуться в процессе использования SObjectizer-а. Смысл в том, что на базе SObjectizer-овских агентов разрабатывается приложение для управления подключенными к компьютеру устройствами. Часть операций (а именно операция инициализации и переинициализации устройства) выполняется синхронно, что приводит к блокировке рабочей нити на некоторое время. Операции же ввода-вывода осуществляются асинхронно, поэтому иницирование чтения/записи и обработка результата чтения-записи выполняются значительно быстрее и не блокируют рабочую нить надолго.
Читать полностью »

Многопоточность на корабликах - 1

Задача производитель/потребитель

Статья рассчитана для новичков, которые недавно начали свое знакомство с миром многопоточноcти на JAVA.
Читать полностью »

Существует два класса задач где нам может потребоваться параллельная обработка: операции ввода-вывода и задачи активно использующие ЦП, такие как обработка изображений. Python позволяет реализовать несколько подходов к параллельной обработке данных. Рассмотрим их применительно к операциям ввода-вывода.

До версии Python 3.5 было два способа реализации параллельной обработки операций ввода-вывода. Нативный метод — использование многопоточности, другой вариант — библиотеки типа Gevent, которые распараллеливают задачи в виде микро-потоков. Python 3.5 предоставил встроенную поддержку параллелизма с помощью asyncio. Мне было любопытно посмотреть, как каждый из них будет работать с точки зрения памяти. Результаты ниже.
Читать полностью »

Когда летом 2016-го года создавалась первая статья про SObjectizer мы говорили, что со временем будем рассказывать и о деталях его реализации, дабы заинтересованные читатели могли заглянуть «под капот». Сегодняшняя статья будет как раз про потроха SObjectizer-а. Про механизм mbox-ов («почтовых ящиков»), который используется для организации взаимодействия акторов (агентов в нашей терминологии).

Почему речь именно про mbox-ы?

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

Зачем нужны mbox-ы?

Почтовые ящики в SObjectizer нужны для того, чтобы организовывать взаимодействие между агентами. Общение между агентами строится посредством асинхронных сообщений и эти самые сообщения нужно куда-то отсылать. Возникает вопрос: «Куда именно?»
Читать полностью »