Какое распределение быстрее?malloc против локальной переменной - PullRequest
10 голосов
/ 05 марта 2012

Какой предпочтительный способ выделить память для функции, которая часто выделяет и освобождает память?Предположим, что эта функция вызывается от 500 до 1000 раз в секунду на процессоре 1 ГГц.

(Пожалуйста, игнорируйте статические и глобальные переменные / распределение. Меня интересует только этот конкретный случай:)

void Test()
{
    ptr=malloc(512)   // 512 bytes
    ...
    free(ptr) 
}

ИЛИ

void Test()
{
     struct MyStruct localvar; // 512 byte sized structure
     ... 
}

Ответы [ 7 ]

20 голосов
/ 05 марта 2012

выделение стека локальных переменных быстрее, чем выделение кучи с malloc.Тем не менее, общее пространство стека ограничено (например, до нескольких мегабайт).Поэтому вы должны ограничить себя «маленькими» данными в локальном стеке.(и 512 байт по сегодняшнему стандарту малы, но 256 Кбайт слишком велики для локального размещения стека).

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

Но вызов malloc несколько тысяч раз в секунду должен быть безболезненным (ИМХО типичный малогабаритный malloc занимает несколько десятков микросекунд).

Для вашего любопытства и за пределами мира C вас может заинтересовать старая статья А.Аппеля Сборка мусора может быть быстрее, чем выделение стека (но, возможно, соображения производительности кэша могут ослабить это утверждение сегодня).

6 голосов
/ 05 марта 2012

Локальные переменные распределяются по существу «бесплатно», поэтому здесь нет никакого соревнования, если мы заинтересованы только в производительности.

Однако:

  • выбор между локальным ипеременная, размещенная в куче, обычно не является чем-то, что вы можете решать без ограничений;обычно есть факторы, которые требуют выбора, поэтому ваш вопрос немного подозрительный, потому что кажется, что он игнорирует эту проблему
  • , в то время как распределение в стеке "свободно" с точки зрения производительности, пробел встек может быть ограничен (хотя, конечно, 512 байт - ничто)
3 голосов
/ 05 марта 2012
  • Какой предпочтителен способ выделения памяти ....
  • Какое распределение быстрее ?

Хотите ли вы более быстрый способ или предпочтительный способ?

Во всяком случае, в случае, если вы упомянули, я думаю, что второй вариант:

struct MyStruct localvar;

более эффективен, поскольку выделение памяти выполняется Stack . Что намного эффективнее, чем использование функций динамического выделения памяти, таких как malloc.

Оптимизация

Кроме того, если вы делаете это для повышения производительности и оптимизации ...

На моем ПК использование malloc для выделения строк вместо объявления массива символов из стека дает мне задержку в ~ 73 наносекунды на строку.

если вы скопировали 50 строк в вашу программу: 4757142/50 = 95142 (и немного) запусков вашей программы

Если я запускаю вашу программу 50 раз в день: 95142/50 = 1902 (и немного) дней

1902 дней = 5 1/5 лет

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

2 голосов
/ 31 октября 2012

Включите дизассемблер при входе в свою функцию и выполните 2 случая.

Локальная переменная (на основе стека) потребует 0 дополнительных циклов - вы даже не увидите, где происходит распределение, потому что функция будет распределять все локальные переменные за 1 цикл, просто перемещая указатель стека и освобождая все локальные переменные в 1 цикле, восстанавливая указатель стека. Неважно, если у вас есть 1 или 1000 локальных переменных, «распределение» занимает столько же времени.

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

Мое эмпирическое правило : всегда используйте стек, если это возможно, вместо malloc/free или new/delete. В дополнение к более высокой производительности вы получаете дополнительное преимущество: вам не нужно беспокоиться о утечке памяти или ресурсов. В C это просто означает, что вы забыли вызвать free(), но в C ++ исключения могут испортить ваш день, если что-то выдает исключение до того, как вы вызовете delete. Если вы используете переменные стека, все это обрабатывается автоматически! Однако используйте стек только в том случае, если речь идет о «маленьких» фрагментах памяти (байтах и ​​КБ), а не о больших объектах (не МБ или ГБ!). В любом случае, если вы говорите об огромных объектах, вы больше не говорите о производительности и, вероятно, в любом случае не будете вызывать free/delete в одном и том же вызове функции.

1 голос
/ 06 марта 2012

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

1 голос
/ 05 марта 2012

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

1 голос
/ 05 марта 2012

Распределение стека происходит быстрее, чем malloc + free.

Распределение стека обычно измеряется в инструкциях, в то время как для malloc + free может потребоваться несколько блокировок (в качестве одного из примеров того, почему это происходитдолго в сравнении).

...