Какова стоимость вызова функции? - PullRequest
33 голосов
/ 18 сентября 2008

По сравнению с

  • Простой доступ к памяти
  • Доступ к диску
  • Доступ к памяти на другом компьютере (в той же сети)
  • Доступ к диску на другом компьютере (в той же сети)

в C ++ для Windows.

Ответы [ 15 ]

27 голосов
/ 18 сентября 2008

относительное время (не должно быть более чем в 100 раз; -)

  • доступ к памяти в кеше = 1
  • вызов функции / возврат в кеш = 2
  • доступ к памяти вне кеша = 10 .. 300
  • доступ к диску = 1000 .. 1e8 (амортизация зависит от количества переданных байтов)
    • зависит в основном от времени поиска
    • Сам перевод может быть довольно быстрым
    • включает как минимум несколько тысяч операций, так как порог пользователь / система должен быть пройден как минимум дважды; запрос ввода / вывода должен быть запланирован, результат должен быть записан обратно; возможно буферы выделены ...
  • сетевые вызовы = 1000 .. 1e9 (амортизация зависит от количества переданных байтов)
    • тот же аргумент, что и с диском ввода / вывода
    • сырая скорость передачи может быть довольно высокой, но какой-то процесс на другом компьютере должен выполнять фактическую работу
19 голосов
/ 18 сентября 2008

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

По сравнению со временем

Вызов функции ~ простой доступ к памяти
Вызов функции <Доступ к диску <br /> Вызов функции <доступ к памяти на другом компьютере <br /> Вызов функции <доступ к диску на другом компьютере </p>

8 голосов
/ 18 сентября 2008

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

По сравнению со всем перечисленным - на порядок меньше.

Это должно относиться практически к любому языку в любой ОС.

4 голосов
/ 18 сентября 2008

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

Для всего остального вызов функции происходит на много (много) величин быстрее.

3 голосов
/ 18 сентября 2008

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

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

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

Если основной вопрос «когда я должен оптимизировать свой код, чтобы минимизировать общее количество выполненных вызовов функций?», То ответ «очень близко к никогда».

3 голосов
/ 18 сентября 2008

Трудно ответить, потому что есть много факторов.

Прежде всего, «Простой доступ к памяти» не прост. Поскольку на современных тактовых частотах процессор может сложить два числа быстрее, чем он получает число с одной стороны чипа на другую (скорость света - это не просто хорошая идея, это ЗАКОН)

Итак, эта функция вызывается внутри кеша памяти процессора? Доступ к памяти вы тоже сравниваете?

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

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

Эта ссылка часто встречается в Google. Для дальнейшего использования я запустил короткую программу на C #, посвященную стоимости вызова функции, и получил ответ: «примерно в шесть раз дороже встроенного». Ниже приведены подробности, см. // Вывод внизу. ОБНОВЛЕНИЕ: чтобы лучше сравнить яблоки с яблоками, я изменил Class1.Method, чтобы он возвращал 'void', вот так: public void Method1 () {// return 0; }
Тем не менее, inline быстрее в 2 раза: inline (avg): 610 мс; вызов функции (в среднем): 1380 мс. Таким образом, ответ, обновленный, «около двух раз».

с использованием системы; using System.Collections.Generic; использование System.Linq; используя System.Text; используя System.Diagnostics;

namespace FunctionCallCost { Программа класса { static void Main (строка [] args) { Debug.WriteLine ( "STOP1"); int iMax = 100000000; // 100M DateTime funcCall1 = DateTime.Now; Секундомер sw = Stopwatch.StartNew ();

        for (int i = 0; i < iMax; i++)
        {
            //gives about 5.94 seconds to do a billion loops, 
          // or 0.594 for 100M, about 6 times faster than
            //the method call.
        }

        sw.Stop(); 

        long iE = sw.ElapsedMilliseconds;

        Debug.WriteLine("elapsed time of main function (ms) is: " + iE.ToString());

        Debug.WriteLine("stop2");

        Class1 myClass1 = new Class1();
        Stopwatch sw2 = Stopwatch.StartNew();
        int dummyI;
        for (int ie = 0; ie < iMax; ie++)
        {
          dummyI =  myClass1.Method1();
        }
        sw2.Stop(); 

        long iE2 = sw2.ElapsedMilliseconds;

        Debug.WriteLine("elapsed time of helper class function (ms) is: " + iE2.ToString());

        Debug.WriteLine("Hi3");


    }
}

// Класс 1 здесь используя Систему; using System.Collections.Generic; использование System.Linq; используя System.Text;

namespace FunctionCallCost { класс Class1 {

    public Class1()
    {
    }

    public int Method1 ()
    {
        return 0;
    }
}

}

// Вывод: STOP1 Истекшее время основной функции (мс): 595 STOP2 Истекшее время вспомогательной функции класса (мс): 3780

STOP1 Истекшее время основной функции (мс): 592 STOP2 Истекшее время функции класса помощника (мс): 4042

STOP1 Истекшее время основной функции (мс): 626 STOP2 Истекшее время функции класса помощника (мс): 3755

1 голос
/ 19 сентября 2008

Давайте не будем забывать, что в C ++ есть виртуальные вызовы (значительно дороже, примерно в x10), а в Windows можно ожидать, что VS будет выполнять встроенные вызовы (0 по определению, так как в двоичном коде не осталось вызовов)

1 голос
/ 18 сентября 2008

Стоимость фактического вызова функции, но не ее полного выполнения? или стоимость фактического выполнения функции? Простая установка вызова функции не является дорогостоящей операцией (обновить ПК?). но очевидно, что стоимость выполнения функции полностью зависит от того, что делает функция.

0 голосов
/ 18 сентября 2008

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

Но вызова можно избежать, если компилятор со встроенной оптимизацией (для компилятора (ов) GCC и не только активирован при использовании уровня оптимизации 3 (-O3)).

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