2014-09-14 2 views
3

Я хотел посмотреть, сколько разницы во времени было бы для использования многопоточного производителя вместо однопоточного. Я настраиваю ActiveMQ на моем локальном компьютере, называет класс производителя, который инициализирует и запускает JMS-соединение в своем конструкторе. Я установил ограничение на сообщение до 3M, и потребовалось около 50 секунд, чтобы отправить все сообщения в ActiveMQ. Я отправил только одну строку «hello world» 3M раз.Single vs Multi-threaded JMS Producer

Затем я использовал один и тот же объект-производитель (одно соединение, но несколько сеансов) и запустил его с помощью ExecutorService с размером потока восемь. В методе run я разделил бы 3M на 8, чтобы убедиться, что каждый поток отправляет не более 375000 сообщений. В этом случае потребовалось около 60 секунд для ввода всех сообщений.

ExecutorService service = Executors.newFixedThreadPool(8); 

    for (int i = 0; i < 8; i++) { 

     service.execute(producer); 
    } 

Затем я создал восемь производителей с каждым производством, имеющей своей собственной связью и побежал их с ExecutorService или нитью размером восемь. На этот раз потребовалось около 68 секунд, чтобы нажать все сообщения 3M.

for (int i = 0; i < 8; i++) { 
     service.execute(new Producer()); 
    } 

Мне интересно, почему один производитель резьбой лучше работает здесь? Я провел каждый сценарий примерно в 10 раз, но результаты остались прежними.

ответ

0

С точки зрения приложения JMS вы написали приложение в многопоточное; несколько сеансов, каждый из которых имеет собственные объекты-производители JMS, управляемые отдельными потоками. Предполагая, что ваше приложение не имеет никаких утверждений о таких ресурсах, как блокировки и т. Д., Это хорошо.

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

Возможно, есть сторона сервера блокировки на стороне сервера данных базовой очереди.

Для ответа на ваш вопрос действительно требуется подробное знание конкретного поставщика JMS.

1

Подключение к Брокеру использует одно соединение TCP/IP для ввода каждого сообщения по проводу. В большинстве случаев было бы нецелесообразно использовать несколько потоков, которые пишут производителю в том же соединении, что и все вызовы станут последовательными, поскольку они проходят через уровень JMS в уровень проводного протокола. В вашем случае это занимает немного больше времени из-за планирования потоков плюс конфликт блокировок плюс накладные расходы на управление пулом потоков.

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

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

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

+0

Спасибо Тиму, в моем последнем сценарии каждая нить откроет совершенно новое соединение, поэтому не будет обмена соединениями, но все равно никакого улучшения. Может быть, потому, что я запускаю как MQ Server, так и Producer на одном компьютере? – Abidi

+0

Тим, я никогда не просил оптимизировать код. Я хотел знать, почему здесь работает многопоточный продюсер. Ваш комментарий по-прежнему не касается моего вопроса. – Abidi

+0

Поскольку несколько потоков не всегда равны более высокой производительности. –

1

Многопоточность может быть медленнее, чем нарезание резьбы по нескольким причинам. Один из них заключается в том, что центральный процессор компьютера является конечным числом и, следовательно, не может одновременно запускать все потоки, делая его медленнее. Другим является то, что у вас также есть конечный объем памяти, из-за чего поток занимает больше времени, так как он занимает больше памяти.

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

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

-------------------------------------- ИЗМЕНЕНИЕ ЧТО ПРОИСХОДИТ: - -------------------------------------------------- -

В вашей проблеме вы сказали, что разделите 3M на 8 для одной однопоточной программы, чтобы она отправила не более 375000 сообщений. Но когда вы многопоточно отправляли все 3M вместо 375000? Если это верно, чем причина, по которой многопоточность работает медленнее, чем одиночная потоковая передача, потому что java не может выполнять разные потоки в то же самое время, похоже, что она работает в то же время из-за скорости ее работы, но она действительно переключается между весь поток, который вы создали. И для перехода между ними требуется немного времени. Несколько наносекунд, поэтому это займет больше времени, хотя каждый поток в многопотоке работает одинаково в одном потоке, он должен переключаться между потоками, которые заставляют занять столь малое количество времени, которое составляет до 8 секунд, что потребовалось для запуска.

+0

Hi PsyCode, я провел 8 потоков на 8 ядер с 8 ГБ оперативной памяти. Я не думаю, что ваша аналогия здесь подходит. – Abidi

+0

Я исправил его в редактировании, я понял, в чем проблема, с которой вы столкнулись, была – PsyCode

0

Мои деньги на концепции Calanais. Вы пытались контролировать приложение во время его работы? Простой инструмент, такой как VisualVM, поможет вам узнать, где потрачено время.

0

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

1

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

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