2010-09-21 2 views
4

Переход через Гетц «Java Параллелизм на практике» книги, он делает дело в отношении использования объекта объединения (раздел 11.4.7) - основные аргументы:Thread-объект локального объединения

1) выделение в Java быстрее C's malloc 2) потоки, запрашивающие объекты из пула, требуют дорогостоящей синхронизации

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

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

+0

Обратите внимание, что (в зависимости от реализации JVM) не каждый объект попадает в кучу (где потребуется сбор мусора); при правильных условиях они могут оказаться в стеке (см. Анализ Escape). – McDowell

+0

@McDowell, я определенно хотел бы увидеть Escape Analysis, но до сих пор в моих тестах (Hotspot 1.6) это только кажется перспективным в микро-тестах. –

+0

Вы получите ответы, которые гораздо полезнее, если вы опишете свою среду и текущую проблему, а не ваш подход к решению этой проблемы. Ваш комментарий о выбросах GC указывает на то, что вы используете огромное количество объектов с длительным сроком службы или огромными объектами. В любом случае пул в потоке, вероятно, является неправильным решением. – Anon

ответ

2

Если его нить местный, то вы можете забыть об этом:

2) потоки, запрашивающие объекты из пула требует дорогостоящей синхронизации

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

+0

Не означает ли «параллелизм» часть названия книги, что речь идет о многопоточности? – luiscubal

+0

Кто говорит, что не многопоточность? Что, если каждый пул потоков имеет свой собственный конкретный набор данных, который не имеет отношения к другим потокам? –

+1

@luiscubal: thread-local не означает многопоточность; это означает пул для каждого потока. поскольку он является приватным для потока, ему не нужно синхронизировать с другими потоками, чтобы выбрать объектную форму, это собственный пул. – Javier

0

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

+0

В пуле есть много зла. –

+0

В словах @Tom есть так много правды. – bestsss

2

В Java 1.4 распределение объектов было относительно дорого, поэтому пулы объектов для простых объектов могли бы помочь. Однако в Java 5.0 размещение объектов значительно улучшилось, однако синхронизация по-прежнему имела смысл понять, что распределение объектов происходит быстрее, чем синхронизация. т. е. удаление пулов объектов улучшает производительность во многих случаях. В Java 6 синхронизация улучшилась до такой степени, что пул объектов может немного повлиять на производительность в простых случаях.

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

Для более сложных/больших объектов пулы объектов могут быть полезны в Java 6, даже если вы используете синхронизацию. например сокет, поток файлов или соединение с базой данных.

2

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

Если вы храните много объектов, все они живут. и если у вас есть несколько ГБ таких объектов, GC собирается тратить много времени на их сканирование напрасно. длинные паузы GC могут парализовать ваше приложение.

кеш-то, что-то, чтобы сделать его не мусором, не помогает GC.

Это не значит, что кеширование неверно. если у вас есть память 15G, а ваша база данных - 10G, почему бы не кэшировать все в памяти, поэтому ответы быстро освещаются. обратите внимание, что это кэширование чего-то, что в противном случае было бы медленным для извлечения.

Чтобы предотвратить бесплодное сканирование кеша 10G, кеш должен находиться вне контроля GC. Например, используйте «memcached», который живет в другом процессе и имеет свой собственный оптимизированный для кеша GC.

последние новости - это BigMemory из Terracotta, которая представляет собой чистое Java-решение, которое делает подобное.


пример локального пула потоков - это прямой пул ByteBuffer от солнца. когда мы называем

channel.read(byteBuffer) 

если ByteBuffer не «прямой», «прямой» один должен быть выделен под капотом, используемый для передачи данных с ОС. в сетевом приложении такие распределения могут быть очень частыми, кажется, что это отходы, чтобы отбросить только что выделенное и немедленно выделить другое в следующем утверждении. инженеры Sun, по-видимому, не очень доверяют GC, создали поток локального пула «прямых» ByteBuffers.

+0

* создал поток локального пула «direct» ByteBuffers * ... и полностью ввернул имплантат. в случае большого кучи-буфера делается попытка записать (выделяет как большой DirectBuffer, копирует все, кроме буфера сокета, не удерживает [2m + data], и процесс повторяется несколько раз). Основная проблема с прямым буфером - это не сам GC; он выполняет свою работу, но очень маленький объект java хранит тонны памяти, и нет никакой информации о том, что он должен быть быстро исправлен. Также для распределения (и освобождения) прямого ByteBuffer требуется глобальная блокировка (+ malloc, free). – bestsss

+0

нет никакой конкретной причины, по которой прямой BB не может управляться внутри VM. то не было бы различия между кучей/прямым BB, и нам не нужно было бы беспокоиться о стоимости нового/GC. К сожалению, этот специальный прямой BB с дополнительной стоимостью. мы должны использовать их для специальных целей. тем не менее, ИО имплантат требует большого количества малых прямых ВВ. Чтобы решить этот конфликт, мы можем выделить один огромный прямой BB и использовать его небольшие фрагменты. Это означает, что нам нужно внедрить систему управления памятью поверх платформы Java. это просто идиотский. – irreputable

+0

адрес памяти прямого буфера не может быть перемещен, в то время как кучи могут быть, то есть адрес закреплен до тех пор, пока буфер остается в живых. Адрес может использоваться native/kernel в любое время, поэтому JVM не имеет никакого контроля. Кстати, я никогда не нуждался в небольших ByteBuffers, я обычно использую один прямой буфер для каждого потока, и если сообщение не вписывается в него, unparsed leftover забуферируется в байтовый байтовый буфер или просто byte []. Почти всегда сообщения могут быть доставлены в виде единого пакета или полностью проанализированы, поэтому в общем случае это работает нормально.Написание состояний машин для синтаксического анализа считается «жестким», tho – bestsss

0

Если это threadlocal, очень вероятно, что вам может даже не понадобиться пул. Конечно, это будет зависеть от вариантов использования, но, скорее всего, в данном потоке вам, вероятно, понадобится только один объект такого типа в данный момент времени.

Предостережение с threadlocals, однако, является управлением памятью. Обратите внимание, что значения threadlocal не исчезают легко, пока нить, которая владеет этими threadlocals, не исчезнет. Поэтому, если у вас есть большое количество потоков и большое количество threadlocals, они могут немного способствовать использованию используемой памяти.

0

Я бы определенно попробовал. Хотя сейчас «общеизвестно», что не нужно заботиться о создании объекта, на самом деле может быть много производительности от использования пулов объектов и конкретных классов. Для рамки обработки файлов я получил 5% производительности чтения из объектов объединения объектов [].

Итак, попробуйте и примите во внимание ваши казни, чтобы увидеть, получаете ли вы что-нибудь.

-2

Джошуа Блох, в Effective Java (Second Edition), говорит:

Второе преимущество статического завода методов является то, что, в отличие от конструкторов, они не требуются, чтобы создать новый объект каждый раз при вызове. Это позволяет неизменные классам использовать preconstructed экземпляров или припрятать экземпляров, как они построены и для выдачи этих экземпляров неоднократно таким образом, чтобы не создавать ненужные повторяющиеся объекты. Метод Boolean.valueOf (boolean) иллюстрирует эту технику: он никогда не создает . Этот метод может значительно повысить производительность, если эквивалентных объектов запрошены часто, особенно если эти объекты дороги для создания.

Я бы сказал, что это зависит. Если это того стоит, сделайте это.

0

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

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

Бассейны хороши для тяжелых объектов, таких как ByteBuffers, особенно. прямые, соединения, сокеты, потоки и т. д. В целом, любые объекты, для которых требуется вмешательство без java.

Смежные вопросы