
Комментарии 14
Сохранять на диск и принимать TCP, значит, можно, а собирать мусор нельзя?
Доброго времени суток, посыл в том что хочется добиться предсказуемого(прогнозируемого) поведения. Работа с сетью, с диском в подобного рода фреймворках может осуществляться асинхронно, не останавливая потоки обработки. Например, в DPDK + VPP, получение пакетов сетевой карты работает в режиме опроса(пулинга), и мы можем прогнозировать задержки получения пакетов.
Отвечая на ваш вопрос, сборка мусора с моем понимании, остановит рабочий поток произвольно, обойдет граф ресурсов для освобождения, в то время как можно было заниматься обработкой.
На практике, хорошие современные инкрементальные сборщики мусора останавливают процессы в худшем случае на десяток миллисекунд. В то время ввод-вывод может создать значительно большие сложности, особенно при ошибках ввода-вывода. Да и вообще, всё что меньше 1/10 секунды, в операционных системах общего назначения малопредсказуемо.
10 ms - это довольно много. За это время можно прилично трафика обработать)
Да и вообще, всё что меньше 1/10 секунды, в операционных системах общего назначения малопредсказуемо.
Это не так, если ядра изолировать
Предположу, что проблема со сборщиком мусора не только в том, что он останавливает процессы. И не в том, что он работает долго или быстро. Прим.: тем более, что выделение памяти может быть хуже: и происходит долго; и блокирует потоки.
Проблема со сборщиком мусора в том, что он ПОЗВОЛЯЕТ создавать "мусор". А когда его позволяют создавать, то сразу появляются желающие его создать (потому, что это проще и удобнее). И это часто приводит к тому, что память начинает выделяться/освобождаться намного чаще, чем нужно: объект -> в другой объект -> в третий объект ... и так далее ... и всё это память.
А если НЕ позволять создавать мусор, то всё начинает работать намного более предсказуемее (хотя и программировать может тяжелее). И язык Си очень хорошо подходит для того, чтобы не создавать мусор: запускается процесс, в котором либо на этапе запуска уже выделена память (например, через сегменты данных), либо (после чтения командной строки или конфигурационного файла) сразу выделяется требуемый набор массивов, списков, блоков памяти. И далее ведётся работа уже с готовой памятью.
Хочешь декодировать jpeg - пожалуйста! Только не в новую память! Вот есть специально выделенный блочок памяти под это - вот там и декодируй. Не хватает размера блочка? Ну либо в командной строке укажи больше размер (и он на старте выделится), либо ... ну не нужны тебе такие jpeg-и. Упс!
Уточнюсь: такими подходами можно писать код и на языках со сборкой мусора. Но обычно так не происходит: такие языки придумывают не для того, чтобы вручную памятью управлять; и программисты, которые десятки лет не следили за памятью, очень болезненно начинают смотреть на этот процесс.
Выбор подходящей структуры
...
Пример 1
...Пример 2
...Пример 3
Это тут к чему, например? Что выбрали то? Выглядит так что выбирать передумали.
Доброго времени суток. Для простоты представления описаны три структуры, каждой из них сопоставлен пример. Возможно не понял вопроса, уточните пожалуйста.
В любой поточной обработке есть ботлнек, проходимость которого должна быть ощутимо больше, чем максимальная нагрузка по входу, а иначе рано или поздно случится лаг (условно выход захлебнулся ненадолго) и при отсутствии уверенного запаса этот лаг может рассасываться очень долго. И что-то мне подсказывает, что на практике затраты на сборку мусора выглядят пылью на фоне этого запаса
Доброго времени суток. Много есть решений. Обычно используют очереди(или кольцевые буферы), чтобы чаще опрашивать источник, и прокручивать обработку без лага. Ещё хорошей практикой будет декомпозировать узкое место(разбить на несколько узлов), тогда аналогичным образом будем чаще опрашивать источник.
Автор не рассмотрел один из интересных случаев, из-за которого потоковую обработку данных часто превращают в пакетную. (да-да, в пакетную).
... и это: ...
Когда несколько источников заходят в один граф. Например, в системах связи (звуковых) это конференция или совещание нескольких участников.
И как только приходят несинхронизированные данные от нескольких источников - сразу начинаешь задумываться об основном вопросе жизни, вселенной и всего остального. Последнее - это сарказм.
А без рассмотрения таких случаев получается всё "чистенько, но бедненько".
могут быть еще чанки, так же многопотоковая обработка чанков с Work Stealing - некии стадии - формирование чанка из конфигурации или соседних частей если они есть - это рефлекторный ответ - или начальная генерация ответа, которая может учитывать уже чанкование. тоесть картинку можно поделить на куски/чанки/области памяти и собирать чанки учитывая соседей, ну как в майнкрафте по-сути, там красивая стейт машина rec/send блоков, потоки - можно указать их число, а мир можно сделать бесконым, вот листы не знаю, может удобно, потомучто получается если смотреть на декодирование картинок в многопотоках, надо делить картинки на чанки учитывая число потоков, а они между собой вычисляют соседей и делают распаковку картинки, тоесть я думал что сначала надо поделить на воркеры, потом нагрузить воркеров, и очищать когда освобождается воркер.
тоесть если представить
строка "123456789"
выделим 9 чанков, кладём на воркеры.
и складываем ответ в строку "987654321" например, 8 потоков 8 воркеров и 1 стилинх поидее, ну образно, я себе так представляю потоковую обработку.
тоесть память нарезается в зависимости от хранилища поделенное на слоты, а воркеры в очереди на количестве потоков выполняют свою область чанка, стыкуя, стыки с соседними поидее.
на С это больно, я дошел только на Расте до этого, там многопоточка есть на mpsc -(mpsc есть и другие типы каналов - библиотеки ) минимальная хотябы, много бойлеркода скипается...
в купе с ускорением через lto и level-optimisation ваще летит клон этот )
Потоковая обработка данных на С