Вопрос

Я имею в виду это обсуждение.Я никогда не писал код на C или C++.У меня нет опыта работы в CS.Однако я работаю Java-разработчиком уже 5 лет и теперь решил узнать больше о CS и немного наверстать упущенное.

Это было полезно?

Решение

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

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

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

Другие советы

http://en.wikipedia.org/wiki/Inlining

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

Как разработчику Java, вам, как правило, не нужно беспокоиться о встраивании методов.Компилятор Java Just-in-time может и будет делать это автоматически в большинстве случаев, когда это имеет смысл.

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

Норман Маурер объясняет на своем блог Подобные встроенные функции JVM и JIT

Встраивание — это метод, который по сути просто «встраивает» один метод в другой и таким образом избавляется от вызова метода. JIT автоматически обнаруживает «горячие» методы и пытается встроить их за вас. Метод считается «горячим», если он был выполнен более X раз, где X — пороговое значение, которое можно настроить с помощью флага JVM при запуске Java (10000 — значение по умолчанию).Это необходимо, поскольку встраивание всех методов принесет больше вреда, чем что-либо еще, из-за огромного объема создаваемого байт-кода.Кроме того, JIT может «вернуть» предыдущий встроенный код, если в более позднем состоянии оптимизация окажется неправильной.Помните, что JIT означает «точно в срок», поэтому оптимизируйте (включая встраивание, а также другие вещи) при выполнении кода.

Также с предупреждением

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

И вы можете найти очень простой пример кода для встраивания кода Java по адресу Ева Андреассон's Java World Post.Вы можете найти соответствующую часть сообщения ниже.

Многие оптимизации пытаются исключить инструкции перехода на машинном уровне (например, JMP для архитектур x86).Команда перехода изменяет регистр указателя команд и тем самым передает поток выполнения.Это дорогостоящая операция по сравнению с другими инструкциями ASSEMBLY, поэтому ее часто приходится сокращать или исключать. Очень полезная и известная оптимизация, направленная на это, называется встраиванием. Поскольку переходы обходятся дорого, может оказаться полезным встроить в вызывающую функцию множество частых вызовов небольших методов с разными адресами входа.Код Java в листингах 3–5 иллюстрирует преимущества встраивания.

Листинг 3.Метод вызывающего абонента

int whenToEvaluateZing(int y) {
   return daysLeft(y) + daysLeft(0) + daysLeft(y+1);
}

Листинг 4.Вызываемый метод

int daysLeft(int x){
   if (x == 0)
      return 0;
   else
      return x - 1;
}

Листинг 5.Встроенный метод

int whenToEvaluateZing(int y){
   int temp = 0;

   if(y == 0) temp += 0; else temp += y - 1;
   if(0 == 0) temp += 0; else temp += 0 - 1;
   if(y+1 == 0) temp += 0; else temp += (y + 1) - 1;

   return temp; 
}

В списках с 3 по 5 вызывающий метод делает три вызова для небольшого метода, который, как мы предполагаем ради этого примера, более полезен для вставки, чем прыгать до трех раз.

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

Листинг 6.После встраивания можно применить дополнительные оптимизации.

int whenToEvaluateZing(int y){
   if(y == 0) return y;
   else if (y == -1) return y - 1;
   else return y + y - 1;
}

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

Стоит отметить, что в ядре Linux некоторое время назад начали отменять встраивание изначально встроенных функций, поскольку стоимость была слишком высокой (более крупные функции потребляли больше кэш-памяти процессора, и возникающие в результате промахи в кэше обходились дороже, чем простой вызов функции которые должны были быть встроены).См. «Главу 15:Встроенная болезнь» в документ/Документация/процесс/кодирование-style.rst Больше подробностей.

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

Это будет более подробно:http://www.codersource.net/cpp_tutorial_inline_functions.html

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

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

РЕДАКТИРОВАТЬ:Обратите внимание, что рефакторинг выполняется вручную или с помощью инструмента;в любом случае это предполагает изменение исходного кода.

Встроенные функции обычно используются в файлах заголовков C++, а не в Java.Заголовочный файл C++ обычно не содержит реализованного кода и считается интерфейсом к одноименному файлу cpp, который обычно содержит реализованный код.Разрешено включать в заголовочный файл встроенную функцию, обычно небольшую облегченную функцию.Встроенные функции обходятся дорого, поэтому они не должны представлять собой операции, требующие большого объема памяти.Для небольших процедур снижение производительности минимально, и они больше используются для удобства.

В этом обсуждении Джон Скит упоминает клиентскую jvm (горячую точку) и серверную jvm с улучшениями производительности, доступными во время выполнения, если JIT-компилятору (точно в срок) разрешено вносить улучшения, основанные на времени.Вот «как это делается» на Java.

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

Сегодня синглтон является предметом многостраничных дискуссий, а развертывание циклов, а также что-то вроде встраивания несколько удалены от их исходного контекста(ов).Вы можете прочитать очень информативную работу Дова Бульки по этому вопросу, чтобы узнать мнение C/C++ по этому вопросу.Что касается Java, изучение его богатых библиотек в java.util лучше отвечает вашим потребностям, чем изучение проблем встраивания и глубокого компилятора - вы можете зациклиться на укоренившейся внутренней войне со структурами данных, которая замалчивает вызовы в 16-битном коде и не останавливайтесь на достигнутом.

Вы можете сделать экземпляр на Java, который напоминает vf-таблицу (пожалуйста, не нагревайтесь), но подумайте об этом, так как вы писали на строго типизированном языке - а теперь будете писать на языке, где строка может легко ускользнуть, ковыряясь. где ему нечего делать.Недавно я пытался написать код, создающий изображение на Java, делая это из кода C.Вскоре я обнаружил, что смотрю таблицу oxr на предмет надежного шифрования — это не имеет ничего общего с кодом, который я писал.

Как бы вы написали строковый класс на C/C++, который имел бы небольшой буфер для строк длиной менее 32 байтов и перехватывал указатели, чтобы они работали только со строкой?

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top