Есть ли снижение производительности / снижение производительности при использовании чистой библиотеки C в коде C ++?

Я видел эту ссылку, но я не прошу снижения производительности кода, использующего «extern». Я имею в виду без «extern», есть ли «переключение контекста» при использовании библиотеки C в C ++?
Есть ли какие-либо проблемы при использовании функций чистого C (не обернутых классом) в приложении C ++?

18

Решение

И C, и C ++ являются языком программирования. технические характеристики (написано на английском языке, см., например, n1570 для спецификации C11) и говорить не о производительности (а о поведении программы, то есть о семантика).

Тем не менее, вы, вероятно, будете использовать такой компилятор, как НКУ или же лязг которые не приносят никакого снижения производительности, поскольку создают одинаковое промежуточное внутреннее представление (например, GIMPLE для GCC и LLVM для Clang) для языков C и C ++, а также потому, что код на C и C ++ совместим с использованием ABIс и соглашения о вызовах.

На практике extern "C" не изменяет соглашение о вызовах, но отключает название искажения. Однако его точное влияние на компилятор является специфическим для этого компилятора. Это может (или нет) отключить встраивание (но рассмотрим -flto для оптимизации времени соединения в GCC).

Некоторые компиляторы C (например, tinycc) производить код с низкой производительностью. Четное НКУ или же лязг, при использовании с -O0 или без эксплицитно что позволяет оптимизация (например, прохождение -O1 или же -O2 и т.д. …) может привести к медленному коду (и оптимизации по умолчанию отключены с ним).

Кстати, C ++ был разработан для взаимодействия с C (и это сильное ограничение объясняет большинство недостатков C ++).

В некоторых случаях подлинный код C ++ может быть немного быстрее, чем соответствующий подлинный код C. Например, чтобы отсортировать массив чисел, вы будете использовать станд :: массив а также станд :: сортировать в подлинном C ++, и операции сравнения в сортировке могут быть встроенными. С кодом C, вы будете просто использовать QSort и каждое сравнение проходит через косвенный вызов функции (потому что компилятор не является встроенным qsort, даже если в теории это могло бы …).

В некоторых других случаях подлинный код C ++ может быть немного помедленнее; например, несколько (но не все) реализации ::operator new просто звонят malloc (затем проверка на отказ), но не встроены.

На практике нет никакого наказания в вызове кода C из кода C ++ или кода C ++ из кода C, поскольку соглашения о вызовах совместимы.

C longjmp средство, вероятно, быстрее, чем выбрасывать исключения C ++, но они не имеют одинаковую семантику (см. разматывание стека) а также longjmp плохо сочетается с кодом C ++.

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


Переключение контекста это концепция, связанная с операционная система а также многозадачность и происходит на процессы Бег Машинный код исполняемый во время преимущественное право покупки. Как это исполнимый получается (из компилятора C, из компилятора C ++, из компилятора Go, из компилятора SBCL или являясь интерпретатором какого-либо другого языка, такого как Perl или байт-код Python), совершенно не имеет значения (поскольку переключение контекста может произойти в любой машина инструкция, во время прерывания). Прочитайте некоторые книги, как Операционные системы: Three Eeasy Pieces.

36

Другие решения

На базовом уровне, нет, вы не увидите никакого типа «переключения» производительности при вызове библиотеки C из кода C ++. Например, вызов из C ++ метода C, определенного в другом модуле перевода, должен иметь примерно такую ​​же производительность, что и вызов того же метода, реализованного в C ++ (таким же образом, как в C), в другом модуле перевода.

Это потому, что общие реализации компиляторов C и C ++ в конечном итоге компилируют исходный код до нативного кода и вызывают extern "C" Функция эффективно поддерживается с использованием того же типа call это может произойти для вызова C ++. Соглашения о вызовах обычно основаны на платформе ABI и аналогичны в любом случае.

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

  • Функции реализованы на C и объявлены extern "C" и вызывается из кода C ++, как правило, не будет встроенным (поскольку по определению они не реализованы в заголовке), что препятствует целому ряду, возможно, очень мощной оптимизации0.
  • Большинство типов данных, используемых в коде C ++1 не может быть непосредственно использован кодом C, поэтому, например, если у вас есть std::string в вашем коде C ++ вам нужно будет выбрать другой тип, чтобы передать его в код C — char * распространено, но теряет информацию о явной длине, которая может быть медленнее, чем решение C ++. Многие типы не имеют прямого эквивалента C, поэтому вы можете столкнуться с дорогостоящим преобразованием.
  • Код C использует malloc а также free для динамического управления памятью, в то время как код C ++ обычно использует new а также delete (и обычно предпочитает скрывать эти вызовы за другими классами, насколько это возможно). Если вам нужно выделить память на одном языке, который будет освобожден на другом, это может привести к несоответствию, когда вам нужно будет перезвонить на «другой» язык, чтобы освободить его, или к ненужным копиям и т. Д.
  • Код C часто интенсивно использует стандартные процедуры библиотеки C, в то время как код C ++ обычно использует методы из стандартной библиотеки C ++. Поскольку существует много функциональных совпадений, возможно, что смесь C и C ++ имеет больший объем кода, чем чистый код C ++, так как используется больше методов библиотеки C2.

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


0 Интересно, что оптимизация во время соединения на самом деле позволяет методам C быть встроенный в C ++ код, что является мало упоминаемым преимуществом LTO. Конечно, это, как правило, зависит от сборки библиотеки C из исходного кода с соответствующими параметрами LTO.

1 Например, почти все, кроме стандартного типа макета.

2 Это, по крайней мере, частично смягчается тем фактом, что многие вызовы стандартной библиотеки C ++ в конечном итоге делегируют подпрограммам библиотеки C для «тяжелого» подъема, такого как std::copy звонки memcpy или же memset когда это возможно и как большинство new реализации в конечном итоге называют malloc,

13

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

Однако C ++ работает во многих различных парадигмах, которых нет в C, поскольку он объектно-ориентирован, и реализует целый спектр абстракций, новых типов данных и операторов. Некоторые типы данных легко переводимы (char * C строка в std::string), а другие нет. Этот раздел на GNU.org о параметрах компилятора C ++ может быть интересным

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

4