Рекомендации по оптимизации производительности и памяти C ++ - PullRequest
5 голосов
/ 31 марта 2010

Есть ли у кого-нибудь ресурс для рекомендаций по оптимизации памяти C ++? Лучшие практики, тюнинг и т. Д.

Как пример:

Class xxx {

    public: 
        xxx();
        virtual ~xxx();

    protected:

    private:

};

Будет ли какая-либо польза от компилятора или выделения памяти, чтобы избавиться от защищенных и приватных, поскольку в этом классе нет защищенных и приватных элементов?

ОБНОВЛЕНИЕ: Что программист делает это:

Class xxx {

    public: 
        xxx();
        virtual ~xxx();

    public:
        more stuff();
        more();

   ifndef __BUILD_WIN__
      public:
        even more();
        envenmore2();
   endif
    protected:

    private:

};

Ответы [ 8 ]

12 голосов
/ 31 марта 2010

У кого-нибудь есть ресурс для рекомендаций по оптимизации памяти C ++? Лучшие практики, тюнинг и т.д?

Это во многом зависит как от вашего компилятора, так и от целевой среды (RISC, Unix / Linux, Windows). Большинство компиляторов будут иметь такую ​​информацию.

Существуют утилиты, которые позволяют отслеживать утечки памяти, чтобы вы могли их исправить во время тестирования. Если вы собираетесь динамически распределять множество вещей (что обычно имеет место в C / C ++), попробуйте убедиться, что вы освободили все, прежде чем уничтожать объект. Для этого:

  • Если вы цените память больше, чем процессор, используйте умные указатели .
  • Если в вашем классе есть переменные-члены, которые являются указателями, убедитесь, что ваш деструктор освобождает каждую из них. Сгруппируйте ваши переменные-члены вместе в исходном коде, чтобы было легко сравнить эти переменные с деструктором.
  • По возможности избегайте динамического выделения памяти, чтобы избежать утечек. Предпочитаю std::string динамически распределенному char* и т. Д.

Будет ли какая-либо польза от компилятор или выделение памяти для получения избавиться от охраняемых и частных там нет предметов, которые защищенный и приватный в этом классе?

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

Кроме того, важно понимать, что компилятор очень интеллектуален (обычно больше, чем программист), поэтому он оптимизирует все, что может; Например, давайте объявляем переменную int a внутри вашего конструктора. И скажем, вы не используете его вообще, вы просто забыли его там. Большинство компиляторов даже не сохранят место в стеке для этих переменных. Другим потребуется, чтобы пользователь активировал Оптимизацию, чтобы это произошло, но, как правило, ваша рабочая версия любой программы должна быть скомпилирована с включенной оптимизацией, даже если она не полная.

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

2 голосов
/ 31 марта 2010

Есть " Эффективный C ++: методы программирования производительности " от Дов Булка и Дэвида Мэйхью. Я не думаю, что это новаторский, но это, безусловно, интересное чтение, которое учит несколько основ.

2 голосов
/ 31 марта 2010

Что ж, компилятору не нужно будет их анализировать, так что у компилятора есть это преимущество.Для чего это стоит (не очень).

Не должно быть никакой разницы в использовании памяти.

Кроме этого, единственное преимущество, о котором я могу подумать, это то, что кто-то, читающий код, имеет меньше потерьиметь дело с (не то, чтобы это было особенно обременительно в вашем примере).

1 голос
/ 31 марта 2010

публичные, защищенные и приватные ключевые слова, вообще не превращают их в объектные файлы, поэтому никакой выгоды вообще нет.

В общем

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

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

0 голосов
/ 27 декабря 2012

Методы оптимизации Существует три типа методов оптимизации кода в C:

вычислительные методы Методы, связанные с памятью Методы привязки ввода / вывода

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

Профилирование Встраивание Разматывание петли Замятие петли Вычисление инвариантов цикла Инверсия петли Устранение хвостовой рекурсии Таблица смотри вверх

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

Местонахождение ссылки Роу-мажорное обращение Уменьшение заполнения Утечки памяти

При оптимизации границ ввода / вывода (I / O) методы последовательного доступа и произвольного доступа используются для сокращения времени, необходимого для получения информации.

Буферизованный ввод / вывод быстрее, чем небуферизованный ввод / вывод. Вы можете использовать функции read () и write () с большими буферами. Вы можете использовать mmap (), чтобы сократить время, необходимое для получения информации. Mmap () сопоставляет адресное пространство процесса с общей памятью или файлом.

еще несколько методов оптимизации:

Минимизируйте использование глобальных переменных в программе.

Объявить все функции, кроме глобальных переменных, как статические в файле.

Используйте переменные размера слова, такие как int и float вместо char, short и double.

Избегайте использования рекурсии.

Избегайте использования функции sqrt (), так как она сильно загружает процессор.

Использовать одномерные массивы.

Не разбивать тесно связанные функции на отдельные файлы.

Используйте функцию put () вместо функции printf.

Использовать неформатированный / двоичный доступ к файлам вместо доступа к форматированным файлам.

Используйте mallopt (), если компилятор поддерживает эту функцию для управления функцией malloc.

Используйте макросы вместо небольших функций для экономии времени процессора.

0 голосов
/ 31 марта 2010

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

  • Оптимизация для повторного использования кэша (блокировка кэша, заполнение и т. Д.)
  • Оптимизировать, чтобы минимизировать попадания TLB (ошибки страницы)
  • Расположите ваши данные как структуры массивов, а не как массивы структур
  • Избегайте ненужных очисток памяти
  • Избегайте перераспределения памяти, вместо этого используйте повторно

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

Что касается беспокойства по поводу объявлений private и protected, то не надо. Они имеют отношение только к компиляции, чтобы обеспечить инкапсуляцию и скрытие данных, и не влияют на сгенерированный двоичный файл.

0 голосов
/ 31 марта 2010

Будет ли какая-либо польза от компилятора или выделения памяти, чтобы избавиться от защищенных и приватных, поскольку в этом классе нет защищенных и приватных элементов?

Нет. AFAIK, не виртуальные методы не увеличивают размер экземпляра класса.

У кого-нибудь есть ресурс для рекомендаций по оптимизации памяти C ++?

1) Если вас беспокоит производительность, используйте профилировщик (например, AQtime). Не угадай, используй инструменты.
2) В целом, не рекомендуется часто (несколько _millions_ раз в секунду) выделять и освобождать память (используя new / delete), особенно большие блоки. По моему опыту такое использование приводит к потере производительности. Если вам часто приходится выделять большой блок памяти с помощью одной и той же подпрограммы (используя new или std :: vector), рассмотрите возможность повторного использования этого же блока при следующем вызове (это будет непросто в многопоточном приложении). То есть вместо

void doStuff(int memSize){
    std::vector<char> buf(memSize);
    //..some code here
}

используйте что-то вроде этого:

void doStuff(int memSize){
    static std::vector<char> buf;
    if (buf.size() < memSize)
        buf.resize(memSize);
    //..some code here
}

Но только в случае необходимости и только в том случае, если вы абсолютно уверены, что эта процедура не может быть вызвана из нескольких отдельных потоков одновременно. (Чтобы сделать его совместимым с многопоточностью, вам понадобятся некоторые хитрости - мьютексы или «пул» из нескольких буферов)
3) Выделение более 1 мегабайта (для windows) или 8 мегабайт (для linux) в стеке вызовет сбой вашей программы (переполнение стека для win, segfault в linux), если вы не указали размер стека во время компиляции. Пример: * +1021 *

void doStuff(){
    char buf[102412];//use new[] or std::vector instead of this.
    //some code here
}

Это все, что я могу придумать. *1024*

0 голосов
/ 31 марта 2010

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

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

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

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