Вызывают ли статические классы проблемы с производительностью в многоядерных системах? - PullRequest
2 голосов
/ 12 декабря 2008

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

Спасибо за ваши комментарии.

Ответы [ 8 ]

14 голосов
/ 12 декабря 2008

Я бы попросил вашего коллегу предоставить данные или как минимум ссылки.

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

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

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

3 голосов
/ 12 декабря 2008

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

Если несколько потоков читают данные, ваш друг категорически не прав.

3 голосов
/ 12 декабря 2008

"[a] статический экземпляр нельзя разделить между кешами процессора. Это верно?"

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

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

Интересно, говорил ли ваш коллега не о производительности, а о необходимости применять правильную блокировку, если несколько потоков читают / записывают одни и те же данные?

2 голосов
/ 12 декабря 2008

На любом языке, контролируемом «виртуальной машиной» (.NET, Java и т. Д.), Этот элемент управления, скорее всего, делегирован базовой ОС и, вероятно, далее - BIOS и другим элементам управления расписанием. При этом в двух крупных компаниях, .NET и Java, статическое и нестатическое - это проблема памяти , а не проблема процессора.

Повторяя точку зрения Сауа, влияние на ЦП оказывает синхронизация и управление потоками, а не доступ к статической информации.

Проблема с управлением кэшем ЦП не ограничивается только статическими методами. Только один процессор может обновлять любой адрес памяти одновременно. Объект в вашей виртуальной машине, и в частности поле в вашем объекте, является указателем на указанный адрес памяти. Таким образом, даже если у меня есть изменяемый объект Foo, вызов setBar(true) для Foo будет разрешен только для одного процессора за раз.

Все это, как говорится, суть .NET и Java в том, что вы не должны тратить свое время на то, чтобы потеть на эти проблемы, пока не сможете доказать , что у вас есть проблема, и я сомневаюсь, что у вас это возникнет. 1015 *

2 голосов
/ 12 декабря 2008

Если вы не используете какие-либо блокировки или синхронизацию, статические и нестатические не будут влиять на вашу производительность.

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

1 голос
/ 12 декабря 2008

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

1 голос
/ 12 декабря 2008
  1. если вы разделяете изменчивые данные между потоками, вам нужен либо алгоритм блокировки, либо алгоритм без блокировки (редко доступен, а иногда, к сожалению, труден в использовании).
    • Имея мало широко используемых ресурсов с блокировкой арбитража, вы можете оказаться в узких местах.
    • статические данные аналогичны ресурсам одного экземпляра.

поэтому:

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

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

0 голосов
/ 12 декабря 2008

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

...