C ++ производительность глобальных переменных - PullRequest
11 голосов
/ 19 мая 2010

Для пояснения: я знаю, как злые глобалы и когда их не следует использовать:)

  • Есть ли какое-либо снижение производительности при доступе / установке глобальной переменной по сравнению с локальной в скомпилированном C ++программа?

Ответы [ 9 ]

20 голосов
/ 19 мая 2010

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

8 голосов
/ 19 мая 2010

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

6 голосов
/ 19 мая 2010

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

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

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

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

5 голосов
/ 19 мая 2010

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

5 голосов
/ 19 мая 2010

Строго говоря, нет.

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

2 голосов
/ 19 мая 2010

Ответ привязан к общей структуре программы.

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

int n = 9;
int main()
{
    for (n = 0; n < 10; ++n)
        printf("%d", n);

    for (int r = 0; r < 10; ++r)
        printf("%d", r);

    return 0;
}

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

1 голос
/ 19 мая 2010

От того, как вы используете данные, хранящиеся в ваших переменных, зависит больше производительности, чем от того, как вы их объявляете. Я не уверен насчет правильной терминологии, но можно определить два типа доступа к данным. Общий доступ (когда вы получаете доступ к одним и тем же данным из разных частей кода) и личные данные, где каждая часть имеет свои собственные данные. По умолчанию глобальные переменные подразумевают общий доступ, а локальные - частный доступ. Но оба типа доступа могут быть достигнуты с обоими типами переменных (то есть локальные указатели, указывающие на один и тот же кусок памяти, или глобальный массив, где каждая часть кода обращается к разной части массива).

Общий доступ имеет лучшее кэширование, меньший объем памяти, но его сложнее оптимизировать, особенно в многопоточной среде. Это также плохо для масштабирования, особенно с архитектурой NUMA ..

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

1 голос
/ 19 мая 2010

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

1 голос
/ 19 мая 2010

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

Опять же, производительность действительно не заслуживает внимания с вашей стороны.

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