Осуществляет ли CLR оптимизацию блокировки? Если нет, то почему? - PullRequest
9 голосов
/ 11 августа 2011

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

Вот хорошее описание уловки:1005 *

http://www.ibm.com/developerworks/java/library/j-jtp10185/

.NET CLR делает что-то подобное?Если нет, то почему бы и нет?

Ответы [ 3 ]

8 голосов
/ 11 августа 2011

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

Другое дело, чтоJava VM использует анализ побега в своем доказательстве.А AFAIK .net не реализовал анализ побега.Другие способы использования escape-анализа, такие как замена распределения кучи на распределение стека, звучат гораздо полезнее и должны быть реализованы в первую очередь.

IMO в настоящее время не стоит усилий по кодированию.В .net VM есть много областей, которые не очень хорошо оптимизированы и имеют гораздо больший эффект.

Векторные инструкции SSE и встраивание делегатов - это два примера, из которых мой код получит гораздо больше пользы, чем от этой оптимизации.1007 *

4 голосов
/ 11 августа 2011

РЕДАКТИРОВАТЬ: Как указывает chibacity ниже, речь идет о том, чтобы сделать замки действительно дешевыми, а не полностью их устранять. Я не верю , что JIT имеет концепцию "локальных объектов потока", хотя я могу ошибаться ... и даже если это не так сейчас, это может произойти в будущем, конечно.

РЕДАКТИРОВАТЬ: Хорошо, приведенное ниже объяснение слишком упрощено, но в действительности оно имеет как минимум некоторую основу :) См. сообщение в блоге Джо Даффи для получения более подробной информации.


Я не могу вспомнить, где я читал это - возможно, "CLR через C #" или "Параллельное программирование в Windows" - но я считаю , что CLR распределяет блоки синхронизации для объектов лениво, только когда это необходимо. Когда объект, монитор которого никогда не был оспорен, заблокирован, заголовок объекта атомарно обновляется с помощью операции сравнения-обмена, чтобы сказать «Я заблокирован». Если другой поток затем попытается получить блокировку, CLR сможет определить, что он уже заблокирован, и в основном обновить эту блокировку до «полной», выделив ей блок синхронизации.

Когда объект имеет «полную» блокировку, операции блокировки обходятся дороже, чем блокировка и разблокировка неоспоримого в противном случае объекта.

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

Я посмотрю, смогу ли я найти доказательства для этого ...

3 голосов
/ 12 августа 2011

В ответ на ваш вопрос: Нет, CLR \ JIT не выполняет оптимизацию "elision lock", т.е. CLR \ JIT не удаляет блокировки из кода, который виден только отдельным потокам.Это можно легко подтвердить с помощью простых однопоточных тестов кода, в которых следует применять блокировку, как и следовало ожидать в Java.

Вероятно, существует ряд причин, по которым этого не происходит, но главным образом этотот факт, что в .Net Framework это, скорее всего, необычная прикладная оптимизация, поэтому не стоит усилий по ее реализации.

Кроме того, в .Net неконтролируемые блокировки очень быстры из-за того, что они не блокируюти выполняется в пространстве пользователя (JVM, похоже, имеют аналогичные оптимизации для непреднамеренных блокировок, например IBM ).Цитировать из C # 3.0 В главе о потоках в Nutshell

Блокировка выполняется быстро: вы можете ожидать, что получите и освободите блокировку менее чем за 100 наносекунд на компьютере с частотой 3 ГГц, еслиблокировка не выполняется "

Несколько примеров сценариев, в которых может применяться блокировка, и почему это того не стоит:

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

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

Использование чужого типа, который объявлен как локальный, который использует блокировки внутренне

Хотя это звучит более полезно, общая философия проектирования .Net Framework - оставить ответственность заили блокировка для клиентов, поэтому типы редко используют внутреннюю блокировку.Действительно, платформа .Net является патологически несинхронизированной, когда речь идет о методах экземпляров для типов, которые специально не предназначены и не рекламируются как параллельные.С другой стороны, у Java есть общие типы, которые включают синхронизацию, например, StringBuffer и Vector.Поскольку .Net BCL в значительной степени несинхронизирован, устранение блокировки, вероятно, будет иметь незначительный эффект.

Сводка

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

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

Я подозреваю, что исключение блокировок возможно благодарявведение анализа побега в JVM, но это не так важно для производительности, как способность советника анализировать, могут ли ссылочные типы выделяться в стеке.

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