LMAX Disruptor: должен клонировать объект EventHandler, полученный от EventHandler#onEvent

У меня есть приложение со многими производителями и потребителями.

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

Мое приложение LogHandler буферизует полученные события в списке, чтобы отправить его в пакетном режиме, как только список достигнет определенного размера. Итак, EventHandler#onEvent помещает полученный объект в список, как только он достигает размера, он отправляет его в RMI на сервер и очищает его.

Мой вопрос: нужно ли мне клонировать объект перед тем, как я внесу его в список, как я понимаю, после использования их можно использовать повторно?

Нужно ли синхронизировать доступ к списку в моем EventHandler#onEvent?


person Community    schedule 18.08.2013    source источник


Ответы (2)


Да - ваше понимание правильное. Вы копируете свои значения в слоты кольцевого буфера и из них.

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

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


Пояснение:

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

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

person jasonk    schedule 18.08.2013
comment
Re: Я бы посоветовал вам клонировать значения при извлечении их из кольцевого буфера и в список обработчиков событий; в противном случае слот может быть повторно использован в вашем ответе, не могли бы вы взглянуть на этот ответ от @ Майкл Баркер и мой недавний комментарий по этому поводу. Это не совсем применимо к потоку выполнения OP, но клонирование данных событий НЕ требуется, если события одного и того же пакета обрабатываются до возврата из обработчика событий с помощью endOfBatch == true, верно? - person OzgurH; 21.09.2019
comment
Да @OzgurH, это хороший момент. Вы правы, вы можете подождать, пока endOfBatch освободит объекты, я не знал, что такое поведение должно было быть частью контракта, так что это полезно знать. Я обновил ответ с разъяснением. Я все еще думаю, что для исходного вопроса они должны намереваться копировать объекты, поскольку контекст вопроса включает пакетную обработку по размеру (я предполагаю, что это означает, что они будут игнорировать endOfBatch и использовать длину списка, чтобы решить, когда отправлять). - person jasonk; 23.09.2019

Можно использовать слоты в RingBuffer Disruptor (включая те, которые содержат List) без клонирования/копирования значений. Это может быть предпочтительным решением для вас в зависимости от того, беспокоитесь ли вы о создании мусора и действительно ли вам нужно беспокоиться о параллельных обновлениях объектов, помещаемых в RingBuffer. Если все объекты, помещаемые в список слотов, являются неизменяемыми или если они обновляются/читаются только одним потоком за раз (предварительное условие, для обеспечения соблюдения которого часто используется Disruptor), их клонирование ничего не даст. поскольку они уже невосприимчивы к гонкам данных.

Что касается пакетной обработки, обратите внимание, что среда Disruptor сама по себе предоставляет механизм для получения элементов из RingBuffer пакетами в ваших потоках EventHandler. Этот подход полностью потокобезопасен и не требует блокировок и может повысить производительность, сделав шаблоны доступа к памяти более предсказуемыми для ЦП.

person Andrew Bissell    schedule 19.08.2013
comment
Не убьет ли это предсказуемые успехи, повышающие производительность разрушителя? - person Juan Bustamante; 08.01.2020