При прослушивании подкаста StackOverflow jab продолжает подходить к тому, что "реальные программисты" записывают на C, а C - намного быстрее, потому что он "близок к машине". Оставив прежнее утверждение для другого сообщения, что особенного в C, что позволяет ему быть быстрее, чем другие языки? Или по-другому: что остановить другие языки от возможности скомпилировать до двоичного файла, который запускается каждый бит так же быстро, как C?
Почему C так быстро, и почему другие языки не такие быстрые или быстрые?
Ответ 1
В C это не так много. Это одна из причин ее быстрого.
Новые языки, поддерживающие сбор мусора, динамическая типизация и другие возможности, которые облегчают программисту программирование программ.
Ловушка - это дополнительные накладные расходы на обработку, которые ухудшают производительность приложения. C не имеет ничего из этого, что означает, что нет накладных расходов, но это означает, что программист должен иметь возможность выделять память и освобождать их, чтобы предотвратить утечки памяти и должен иметь дело со статической типизацией переменных.
Тем не менее, многие языки и платформы, такие как Java (с его Java Virtual Machine) и .NET(с его Common Language Runtime) с годами улучшали производительность с помощью таких приемов, как компиляция точно в срок, которая создает собственный машинный код из байт-кода для достижения более высокой производительности.
Ответ 2
Существует компромисс с дизайнерами C. Это означает, что они приняли решение о превышении безопасности. C не будет
- Проверка привязки индекса массива
- Проверить значения неинициализированных переменных
- Проверьте наличие утечек памяти
- Проверить наличие разворота нулевого указателя
При индексировании в массив, в Java требуется некоторый вызов метода на виртуальной машине, проверка привязки и другие проверки работоспособности. Это действительно и абсолютно нормально, потому что он добавляет безопасность там, где это необходимо. Но в C даже довольно тривиальные вещи не ставятся в безопасности. Например, C не требует memcpy для проверки того, копируют ли регионы дубликаты. Он не разработан как язык программирования большого бизнес-приложения.
Но эти проектные решения не являются ошибками на языке C. Они по дизайну, так как позволяют компиляторам и библиотечным редакторам получать каждый бит производительности из компьютера. Вот дух C, как это объясняет C Обоснование:
C-код может быть не переносимым. Несмотря на то, что он стремился дать программистам возможность писать действительно портативные программы, Комитет не хотел принуждать программистов писать переносимо, чтобы исключить использование C как "высокоуровневый ассемблер": способность писать машинный код является одной из сильных сторон C.
Сохраняйте дух C. Комитет сохранил главную цель - сохранить традиционный дух C. Существует множество аспектов духа C, но суть - это чувство сообщества. основополагающие принципы, на которых основан язык C. Некоторые из аспектов духа C можно резюмировать в фразах типа
- Доверяйте программисту.
- Не препятствуйте программисту делать то, что нужно сделать.
- Держите язык небольшим и простым.
- Предоставьте только один способ выполнить операцию.
- Сделайте это быстро, даже если он не гарантированно переносится.
Последняя пословица нуждается в небольшом объяснении. Потенциал для эффективной генерации кода является одной из наиболее важных сильных сторон C. Чтобы гарантировать, что взрыв кода не происходит для того, что кажется очень простой операцией, многие операции определяются как то, как аппаратное обеспечение целевой машины делает это, а не посредством общее абстрактное правило. Пример этой готовности жить с тем, что делает машина, можно увидеть в правилах, которые регулируют расширение объектов char для использования в выражениях: расширяются ли значения объектов char до подписанных или неподписанных величин, как правило, зависит от того, операция байта более эффективна на целевой машине.
Ответ 3
Если вы потратили месяц на создание чего-то в C, который работает через 0,05 секунды, и я трачу день на то, чтобы писать то же самое на Java, и он работает через 0,10 секунды, тогда C действительно быстрее?
Однако, чтобы ответить на ваш вопрос, хорошо написанный код C, как правило, работает быстрее, чем хорошо написанный код на других языках, потому что часть написания кода C "хорошо" включает в себя ручную оптимизацию на близком расстоянии, уровень машины.
Несмотря на то, что компиляторы очень умны, они еще не способны творчески придумать код, который конкурирует с ручными массированными алгоритмами (предполагая, что "руки" принадлежат программисту хорошего C).
Edit:
Много комментариев написано так: "Я пишу на C, и я не думаю об оптимизации".
Но взять конкретный пример из этого сообщения:
В Delphi я мог бы написать это:
function RemoveAllAFromB(a, b: string): string;
var
before, after :string;
begin
Result := b;
if 0 < Pos(a,b) then begin
before := Copy(b,1,Pos(a,b)-Length(a));
after := Copy(b,Pos(a,b)+Length(a),Length(b));
Result := before + after;
Result := RemoveAllAFromB(a,Result); //recursive
end;
end;
а в C я пишу это:
char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
for (j = 0; j < len2; j++) {
if (s1[i] == s2[j]) {
break;
}
}
if (j == len2) { /* s1[i] is not found in s2 */
*result = s1[i];
result++; /* assuming your result array is long enough */
}
}
Но сколько оптимизаций существует в версии C? Мы принимаем много решений о реализации, о которых я не думаю в версии Delphi. Как реализована строка? В Delphi я этого не вижу. В C я решил, что это будет указатель на массив целых чисел ASCII, которые мы называем символами. В C мы проверяем существование символа по одному за раз. В Delphi я использую Pos.
И это всего лишь небольшой пример. В большой программе программист C должен принимать такие решения на низком уровне с помощью нескольких строк кода. Это добавляет к ручному, ручному оптимизированному исполняемому файлу.
Ответ 4
Я этого не видел, поэтому я скажу: C имеет тенденцию быть быстрее, потому что почти все остальное написано в C.
Java построен на C, Python построен на C (или Java, или .NET и т.д.), Perl и т.д. OS написана на C, виртуальные машины написаны на C, составлены компиляторы в C интерпретаторы написаны на C. Некоторые вещи все еще написаны на языке ассемблера, который, как правило, еще быстрее. Все больше и больше вещей написано во что-то еще, что само написано на C.
Каждый оператор, который вы пишете на других языках (а не Assembly), обычно реализуется под несколькими инструкциями в C, которые скомпилированы с использованием собственного машинного кода. Поскольку эти другие языки имеют тенденцию существовать для того, чтобы получить более высокий уровень абстракции, чем C, те дополнительные утверждения, которые требуются в C, обычно ориентированы на добавление безопасности, добавление сложности и обеспечение обработки ошибок. Это часто хорошие вещи, но они имеют стоимость, а ее имена скорость и размер.
Лично я написал буквально десятки языков, охватывающих большую часть доступного спектра, и я лично искал волшебство, на которое вы намекаете:
Как я могу взять свой пирог и съесть его? Как я могу играть с абстракциями высокого уровня на моем любимом языке, а затем опускаться до нужного размера C для скорости?
После нескольких лет исследований мой ответ - Python (на C). Возможно, вы захотите его взглянуть. Кстати, вы также можете спуститься к сборке с Python (с небольшой помощью из специальной библиотеки).
С другой стороны, плохой код может быть написан на любом языке. Поэтому код C (или сборка) не выполняется автоматически быстрее. Аналогично, некоторые оптимизационные трюки могут принести части кода языка более высокого уровня близко к уровню производительности raw C. Но для большинства приложений ваша программа тратит большую часть своего времени на людей или оборудование, поэтому разница действительно не имеет значения.
Enjoy.
Ответ 5
В нем много вопросов - в основном я не готов ответить. Но для этого последнего:
чтобы остановить другие языки от возможности скомпилировать до двоичного файла, который запускает каждый бит так же быстро, как C?
Одним словом, Абстракция.
C - это только один или два уровня абстракции от машинного языка. Языки Java и .Net имеют как минимум 3 уровня абстракции от ассемблера. Я не уверен в Python и Ruby.
Как правило, чем больше игрушек-программистов (сложные типы данных и т.д.), тем дальше вы работаете с машинным языком и тем больше переводов должно быть сделано.
Я здесь и там, но это основной смысл.
Обновить. Есть несколько хороших комментариев к этому сообщению с более подробной информацией.
Ответ 6
Это не так, что C работает быстро, поскольку эта модель C-стоимости прозрачна. Если программа C работает медленно, это происходит медленным образом: путем выполнения множества утверждений. По сравнению со стоимостью операций на C, операции высокого уровня над объектами (особенно отражение) или строки могут иметь затраты, которые не очевидны.
Два языка, которые обычно компилируются в двоичные файлы, которые так же быстры, как C, являются стандартными ML (используя MLton компилятор) и Objective Caml. Если вы посмотрите Great Language Shootout, вы обнаружите, что для некоторых тестов, например бинарных деревьев, версия OCaml быстрее, чем C. (I не нашел никаких записей MLton.) Но не слишком серьезно относитесь к перестрелке; это, как говорится, игра, результаты часто отражают, сколько усилий люди внесли в настройку кода.
Ответ 7
C не всегда быстрее.
C работает медленнее, чем, например, Modern Fortran.
C часто бывает медленнее, чем Java для некоторых вещей. (Особенно после того, как компилятор JIT запустил ваш код)
C позволяет сбрасывать указатель, что означает, что некоторые хорошие оптимизации невозможны. В частности, когда у вас несколько исполнительных блоков, это приводит к сбоям при наборе данных. Вл.
Предположение о том, что операция арифметики указателей на самом деле приводит к медленной раздутой производительности в некоторых семействах процессоров (особенно это относится к PIC), использовалась для отсоса больших сегментов х86.
В принципе, когда вы получаете векторную единицу или распараллеливающий компилятор, C воняет и современный Fortran работает быстрее.
C программные трюки, такие как thunking (изменение исполняемого файла "на лету" ), вызывают блокировки предварительной выборки CPU.
Вы получаете дрейф?
Любой наш добрый друг, x86, выполняет набор команд, который в наши дни не имеет отношения к фактической архитектуре процессора. Теневые регистры, оптимизаторы загрузки-загрузки, все в ЦП. Таким образом, C приближается к виртуальному металу. Настоящий металл Intel не позволяет вам видеть. (Исторически процессор VLIW был немного расстроен, возможно, это не так уж плохо.)
Если вы программируете на C на высокопроизводительном DSP (возможно, TI DSP?), компилятор должен сделать некоторые сложные вещи, чтобы развернуть C по нескольким параллельным исполнительным устройствам. Итак, C не близок к металлу, но он близок к компилятору. Что будет делать вся программа оптимизации. Weird.
Наконец, некоторые CPU (www.ajile.com) запускают байт-коды Java на аппаратном уровне. C будет использовать PITA на этом CPU.
Ответ 8
что остановить другие языки от возможность скомпилировать до двоичного который работает каждый бит так же быстро, как C?
Ничего. Современные языки, такие как Java или .NET, ориентированы больше на производительность программистов, а не на производительность. Сегодня оборудование дешево. Также компиляция промежуточного представления дает множество бонусов, таких как безопасность, переносимость и т.д..NET CLR может воспользоваться преимуществами другого оборудования - например, вам не нужно вручную оптимизировать/перекомпилировать программу для использования набора инструкций SSE.
Ответ 9
Основными факторами являются то, что это статически типизированный язык и скомпилированный для машинного кода. Кроме того, поскольку это низкоуровневый язык, он обычно не делает ничего, о чем вы не говорите.
Это некоторые другие факторы, которые приходят на ум.
- Переменные не инициализируются автоматически
- Проверка границ по массивам
- Непроверенная манипуляция указателем
- Проверка целостности целых чисел
- Статически типизированные переменные
- Функциональные вызовы являются статическими (если вы не используете указатели на функции)
- У авторов компилятора было много времени, чтобы улучшить оптимизирующий код. Кроме того, люди программируют на C с целью получения максимальной производительности, поэтому есть давление для оптимизации кода.
- Части спецификации языка определены в соответствии с реализацией, поэтому компиляторы могут делать все наиболее оптимальным образом.
Большинство статически типизированных языков могут быть скомпилированы так же быстро или быстрее, чем C, особенно если они могут сделать предположения, что C не может из-за сглаживания указателя и т.д.
Ответ 10
Я думаю, вы забыли, что язык ассемблера также является языком:)
Но серьезно, программы C быстрее, только когда программист знает, что он делает. Вы можете легко написать программу на C, которая работает медленнее, чем программы, написанные на других языках, которые выполняют ту же работу.
Причина, по которой C работает быстрее, заключается в том, что она разработана таким образом. Это позволяет вам делать много "более низкого уровня", что помогает компилятору оптимизировать код. Или, скажем так, вы, программист, отвечаете за оптимизацию кода. Но это часто довольно сложно и подвержено ошибкам.
Другие языки, как уже упоминалось, больше ориентированы на производительность программиста. Считается, что время программиста намного дороже машинного времени (даже в старые времена). Поэтому имеет смысл свести к минимуму время, затрачиваемое программистами на письма и отладки программ, а не на время работы программ. Для этого вы немного пожертвуете тем, что можете сделать, чтобы сделать программу быстрее, потому что много вещей автоматизировано.
Ответ 11
Я не думаю, что кто-то упомянул тот факт, что в компиляторы C было добавлено больше усилий, чем любой другой компилятор, возможно, за исключением Java.
C чрезвычайно оптимизирован для многих из уже заявленных причин - более чем на любом другом языке. Поэтому, если такое же количество усилий будет добавлено в компиляторы других языков, C, вероятно, все же выйдет на первое место.
Я думаю, что есть хотя бы один язык-кандидат, который с оптимизмом может быть оптимизирован лучше, чем C, и поэтому мы могли бы видеть реализации, которые производят более быстрые двоичные файлы. Я думаю о цифровых марках D, потому что создатель позаботился о создании языка, который потенциально может быть лучше оптимизирован, чем C. Возможно, существуют другие языки, которые имеют такую возможность. Однако я не могу себе представить, что любой язык будет иметь компиляторы более чем на несколько процентов быстрее, чем лучшие компиляторы C. Я хотел бы ошибаться.
Я думаю, что настоящие "низкие висячие фрукты" будут на языках, которые предназначены для того, чтобы быть легким для людей, чтобы оптимизировать. Опытный программист может сделать любой язык быстрее, но иногда вам приходится делать смешные вещи или использовать неестественные конструкции, чтобы это произошло. Хотя он всегда будет прилагать усилия, хороший язык должен давать относительно быстрый код, не зацикливаясь на том, как именно написана программа.
Также важно (по крайней мере для меня), что код наихудшего кода имеет тенденцию быть быстрым. В Интернете существует множество "доказательств", что Java работает так же быстро или быстрее, чем C, но это основано на примерах выбора вишни. Я не большой поклонник C, но я знаю, что что-то, что я пишу на C, будет хорошо работать. С Java он "вероятно" будет работать в пределах 15% от скорости, обычно в пределах 25%, но в некоторых случаях это может быть намного хуже. Любые случаи, когда это так же быстро или в пределах пары процентов, как правило, объясняются тем, что большую часть времени он проводит в библиотечном коде, который в любом случае сильно оптимизирован.
Ответ 12
В большинстве случаев каждая инструкция C соответствует очень немногим инструкциям ассемблера. Вы, по сути, пишете машинный код более высокого уровня, поэтому вы контролируете почти все, что делает процессор. Многие другие скомпилированные языки, такие как С++, имеют много простых инструкций, которые могут превратиться в гораздо больше кода, чем вы думаете (виртуальные функции, конструкторы копирования и т.д.). И интерпретируемые языки, такие как Java или Ruby, имеют еще один слой инструкции, которые вы никогда не видите - виртуальная машина или интерпретатор.
Ответ 13
На самом деле это немного увековеченная ложь. Хотя верно, что C-программы часто бывают быстрее, это не всегда так, особенно если программист C не очень хорош в этом.
Одно большое яркое отверстие, о котором люди склонны забывать, - это когда программа должна блокировать какой-то IO, такой как ввод пользователя в любую графическую программу. В этих случаях на самом деле не имеет значения, какой язык вы используете, поскольку вы ограничены скоростью, с которой могут поступать данные, а не с какой скоростью вы можете ее обрабатывать. В этом случае это не имеет большого значения, если вы используете C, Java, С# или даже Perl; вы просто не можете идти быстрее, чем могут поступать данные.
Другим важным моментом является то, что использование коллекции мусора и не использование правильных указателей позволяет виртуальной машине сделать ряд оптимизаций, недоступных на других языках. Например, JVM способен перемещать объекты вокруг кучи для дефрагментации. Это делает будущие распределения намного быстрее, поскольку следующий индекс можно просто использовать, а не искать в таблице. Современные JVM также не должны фактически освобождать память; вместо этого они просто перемещают живые объекты вокруг, когда они GC и отработанная память от мертвых объектов восстанавливаются по существу бесплатно.
Это также вызывает интересную мысль о C и тем более в С++. Существует что-то вроде философии дизайна "Если вам это не нужно, вы не платите за это". Проблема в том, что если вы этого хотите, вы в конечном итоге платите через нос за это. Например, реализация vtable в Java, как правило, намного лучше, чем реализации С++, поэтому вызовы виртуальных функций намного быстрее. С другой стороны, у вас нет выбора, кроме как использовать виртуальные функции в Java, и они все равно стоят чего-то, но в программах, использующих множество виртуальных функций, уменьшается стоимость.
Ответ 14
Многие из этих ответов дают веские основания для того, почему C быстрее или быстрее (как в общем, так и в конкретных сценариях). Несомненно, что:
- Многие другие языки предоставляют автоматические функции, которые мы считаем само собой разумеющимися. Например, проверка границ, проверка типа времени выполнения и автоматическое управление памятью не предоставляются бесплатно. По крайней мере, некоторые из них связаны с этими функциями, о которых мы, возможно, и не думаем или даже не осознаем, при написании кода, который использует эти функции.
- Шаг от источника к машине часто не так прямо на других языках, как в C.
- OTOH, сказать, что скомпилированный код C выполняется быстрее, чем другой код, написанный на других языках, является обобщением, которое не всегда верно. Контр-примеры легко найти (или изобретать).
Несмотря на это, есть еще кое-что, что я заметил, что, я думаю, влияет на сравнительную производительность C по сравнению со многими другими языками больше, чем любой другой фактор. К остроумию:
Другие языки часто упрощают запись кода, который выполняется медленнее. Часто это даже поощряется философией дизайна языка. Следствие: программист С с большей вероятностью пишет код, который не выполняет ненужные операции.
В качестве примера рассмотрим простую программу Windows, в которой создано одно главное окно. Версия C заполнит структуру WNDCLASS[EX]
, которая будет передана в RegisterClass[Ex]
, затем вызовите CreateWindow[Ex]
и введите цикл сообщения. Ниже приведен упрощенный упрощенный и сокращенный код:
WNDCLASS wc;
MSG msg;
wc.style = 0;
wc.lpfnWndProc = &WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWndCls";
RegisterClass(&wc);
CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
эквивалентной программой в С# может быть только одна строка кода:
Application.Run(new Form());
Эта одна строка кода предоставляет все функции, которые выполнялись почти 20 строками кода C, и добавляет некоторые вещи, которые мы оставили, например, проверку ошибок. Более богатая, более полная библиотека (по сравнению с теми, которые использовались в типичном проекте C) сделала для нас большую работу, освободив наше время, чтобы написать еще много фрагментов кода, которые выглядят короче для нас, но включают в себя много шагов за кулисами.
Но богатая библиотека, позволяющая легко и быстро раздувать код, на самом деле не моя точка зрения. Моя точка зрения более очевидна, когда вы начинаете изучать, что на самом деле происходит, когда на самом деле выполняется наш маленький однострочный. Для удовольствия когда-нибудь включить доступ к .NET-источнику в Visual Studio 2008 или выше и перейдите в простую однострочную строку выше. Один из забавных маленьких камней, с которыми вы столкнетесь, - это комментарий в getter для Control.CreateParams
:
// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
//
if (createParams == null) {
createParams = new CreateParams();
}
Десять раз. Информация, примерно эквивалентная сумме того, что хранится в структуре WNDCLASSEX
и переданная в CreateWindowEx
, извлекается из класса Control
десять раз, прежде чем она будет сохранена в структуре WNDCLASSEX
и передана на RegisterClassEx
и CreateWindowEx
.
В целом количество инструкций, выполненных для выполнения этой самой основной задачи, на 2-3 порядка больше на С#, чем на C. Часть этого объясняется использованием многофункциональной библиотеки, которая обязательно обобщенный, по сравнению с нашим простым C-кодом, который делает именно то, что нам нужно, и не более того. Но часть этого объясняется тем, что модульный, объектно-ориентированный характер платформы .NET, поддается многому повторению исполнения, которого часто избегают процедурный подход.
Я не пытаюсь выбрать С# или .NET framework. Я также не говорю, что модуляция, обобщение, функции библиотеки/языка, ООП и т.д. - это плохие вещи. Я использовал большую часть своего развития в C, позже на С++, а в последнее время в С#. Аналогично, до C я использовал большую сборку. И с каждым шагом "выше" мой язык идет, я пишу лучше, более удобные, более надежные программы за меньшее время. Однако они имеют тенденцию к более медленному выполнению.
Ответ 15
С++ быстрее в среднем (так как изначально он был супер-набором C). Однако для конкретных эталонов часто существует другой язык, который быстрее.
http://shootout.alioth.debian.org/u32/benchmark.php
fannjuch-redux был самым быстрым в Scala
n-body, fasta были быстрее в Ada.
спектральная норма была наиболее быстрой в Фортране.
reverse-комплемент, mandelbrot, pidigits были наиболее быстрыми в ATS.
regex-dna был самым быстрым в JavaScript.
chameneou-redux был быстрее всего - это Java 7.
thread-ring был самым быстрым в Haskell.
Остальные тесты были самыми быстрыми на C или С++.
Ответ 16
Отсутствие абстракции - это то, что делает C быстрее. Если вы пишете вывод, вы точно знаете, что происходит. Если вы пишете выходной оператор в java, он скомпилируется в файл класса, который затем запускается на виртуальной машине, представляя прокрутку абстракции. Отсутствие объектно-ориентированных функций как части языка также увеличивает его скорость до меньшего генерируемого кода. Если вы используете C как объектно-ориентированный язык, тогда вы делаете все кодирование для таких вещей, как классы, невнимательность и т.д. Это значит, а затем сделать что-то общее для всех с количеством кода и степенью производительности, требующей от вас только записи что вам нужно для выполнения этой работы.
Ответ 17
Удивительно видеть старый "C/С++ должен быть быстрее, чем Java, потому что Java интерпретируется". Миф все еще жив и пинает. Есть статьи, возвращающиеся на несколько лет, а также более свежие которые объясняют понятиями или измерениями, почему это не всегда так.
Существующие реализации виртуальной машины (и не только JVM, кстати) могут использовать информацию, собранную во время выполнения программы, для динамической настройки кода при его запуске с использованием различных методов:
- рендеринг частых методов машинного кода,
- вложение небольших методов,
- настройка блокировки
и множество других настроек, основанных на знании того, что действительно делает код, и о фактических характеристиках среды, в которой она работает.
Ответ 18
Самый быстрый код будет тщательно обработан машинным кодом. Ассемблер будет почти таким же хорошим. Оба уровня очень низкого уровня, и для написания кода требуется много кода для написания. C немного выше ассемблера. У вас все еще есть возможность управлять вещами на очень низком уровне в реальной машине, но есть достаточно абстракции, чтобы писать быстрее и легче, чем ассемблер. Другие языки, такие как С# и JAVA, еще более абстрактны. Хотя ассемблер и машинный код называются низкоуровневыми языками, С# и JAVA (и многие другие) называются языками высокого уровня. C иногда называют языком среднего уровня.
Ответ 19
Это не столько язык, сколько инструменты и библиотеки. Доступные библиотеки и компиляторы для C намного старше, чем для более новых языков. Вы можете подумать, что это сделает их медленнее, но au contraire.
Эти библиотеки были написаны в то время, когда обработка мощности и памяти была высокой. Они должны были быть написаны очень эффективно, чтобы работать вообще. Разработчики компиляторов C также долгое время работали во всех видах умных оптимизаций для разных процессоров. C зрелость и широкое усыновление делают существенное преимущество перед другими языками того же возраста. Это также дает C преимущество скорости над более новыми инструментами, которые не подчеркивают сырую производительность, как это делал C.
Ответ 20
Я знаю, что многие люди говорили это длинным образом, но:
C быстрее, потому что он меньше (для вас).
Ответ 21
Вернувшись в хорошие дни, были только два типа языков: скомпилированы и интерпретированы.
Скомпилированные языки использовали "компилятор", чтобы читать синтаксис языка и преобразовывать его в идентичный код языка ассемблера, который может быть только непосредственно на CPU. Интерпретированные языки использовали несколько различных схем, но по существу синтаксис языка был преобразован в промежуточную форму, а затем запущен в "интерпретаторе", среде для выполнения кода.
Таким образом, в некотором смысле, существует еще один "слой" - интерпретатор - между кодом и машиной. И, как всегда в случае с компьютером, больше означает, что больше ресурсов используется. Переводчики были медленнее, потому что им приходилось выполнять больше операций.
Совсем недавно мы видели больше гибридных языков, таких как Java, которые используют как компилятор, так и интерпретатор, чтобы заставить их работать. Это сложно, но JVM работает быстрее, сложнее и более оптимизирован, чем старые интерпретаторы, поэтому значительно улучшается смена исполнения (с течением времени) ближе к прямому скомпилированному коду. Конечно, новые компиляторы также имеют более привлекательные оптимизационные трюки, поэтому они, как правило, генерируют лучший код, чем раньше. Но большинство оптимизаций, чаще всего (хотя и не всегда), делают некоторые виды компромиссов такими, что они не всегда быстрее при любых обстоятельствах. Как и все остальное, ничто не приходит бесплатно, поэтому оптимизаторы должны хвастаться от чего-то (хотя часто это время использует процессор времени компиляции для экономии времени исполнения процессора).
Возвращаясь к C, это простой язык, который можно скомпилировать в довольно оптимизированную сборку, а затем запустить непосредственно на целевой машине. В C, если вы увеличиваете целое число, более чем вероятно, что это только один шаг ассемблера в ЦП, но в Java он может оказаться намного больше (и может включать в себя также сбор мусора) -) C предлагает вам абстракцию, приближающуюся к машине (ассемблер является ближайшей), но вы в конечном итоге должны сделать больше работы, чтобы добиться этого, и он не защищен, прост в использовании и не подходит для ошибок. Большинство других языков дают вам более высокую абстракцию и заботятся о дополнительных деталях для вас, но в обмен на их расширенную функциональность им требуется больше ресурсов для запуска. По мере того, как вы обобщаете некоторые решения, вам приходится обращаться с более широким спектром вычислений, что часто требует больших ресурсов.
Павел.
Ответ 22
Некоторые алгоритмы С++ быстрее, чем C, а некоторые реализации алгоритмов или шаблонов проектирования на других языках могут быть быстрее, чем C.
Когда люди говорят, что C быстро, а затем переходят к разговору о каком-то другом языке, они обычно используют производительность C в качестве эталона.
Ответ 23
С современными оптимизирующими компиляторами очень маловероятно, что чистая программа на C будет намного быстрее, чем скомпилированный код .net, если вообще. С повышением производительности, которое инфраструктура, например .net, предоставляет разработчику, вы можете делать что-то в течение дня, который обычно занимал недели или месяцы в обычном C. В сочетании с дешевой стоимостью аппаратного обеспечения по сравнению с зарплатой разработчика, это просто ПРАВИЛЬНО писать материал на языке высокого уровня и бросать оборудование при любой медленности.
Причина, по которой Джефф и Джоэл говорят о том, что C является языком "реального программиста", заключается в том, что в C. нет необходимости удерживать руки. Вы должны выделить свою собственную память, освободить эту память, провести собственную проверку границ и т.д. нет такой вещи, как новый объект(); Нет коллекции мусора, классов, ООП, инфраструктур сущностей, LINQ, свойств, атрибутов, полей или чего-либо подобного. Вы должны знать такие вещи, как арифметика указателей и как разыменовывать указатель. И, если на то пошло, знать и понимать, что такое указатель. Вы должны знать, что такое стек стека и что такое указатель инструкции. Вы должны знать модель памяти архитектуры процессора, над которой вы работаете. Существует много неявного понимания архитектуры микрокомпьютера (как правило, микрокомпьютера, над которым вы работаете) при программировании на C, который просто отсутствует или не нужен при программировании на чем-то вроде С# или Java. Вся эта информация была отключена программистом компилятора (или VM).
Ответ 24
1) Как говорили другие, C делает меньше для вас. Нет инициализирующих переменных, проверки границ массива, управления памятью и т.д. Эти функции на других языках стоят памяти и циклов ЦП, которые C не тратит.
2) Ответы, говорящие о том, что C менее абстрагируется и, следовательно, быстрее, только наполовину правильны. С технической точки зрения, если бы у вас был "достаточно продвинутый компилятор" для языка X, то язык X мог приблизиться или равняться скорости C. Разница с C заключается в том, что, поскольку он так явно отображен (если вы прошли курс архитектуры) и прямо на язык ассемблера, который даже наивный компилятор может сделать достойную работу. Для чего-то вроде Python вам нужен очень продвинутый компилятор для прогнозирования вероятных типов объектов и генерации машинного кода на лету. Семантика C достаточно проста, что простой компилятор может преуспеть.
Ответ 25
Не используйте для этого какое-либо слово, посмотрите на разборку как для C, так и для вашего языка по выбору в любой критичной для производительности части вашего кода. Я думаю, вы можете просто посмотреть в окне разборки во время выполнения в Visual Studio, чтобы увидеть дизассемблированную .Net. Должно быть возможным, если сложно использовать Java с помощью windbg, хотя если вы это сделаете с .Net, многие из проблем будут одинаковыми.
Я не люблю писать на C, если мне это не нужно, но я думаю, что многие из утверждений, сделанных в этих ответах, которые касаются скорости других языков, отличных от C, можно отложить, просто разобрав ту же рутину в C и на вашем более высоком уровне выбора языка, особенно если задействовано большое количество данных, что характерно для приложений с критическими характеристиками. Fortran может быть исключением в своей области знаний, не знаю. Является ли это более высоким уровнем, чем C?
В первый раз, когда я сравнил JITed-код с собственным кодом, разрешил все и все вопросы о том, может ли код .Net работать с C-кодом. Дополнительный уровень абстракции и все проверки безопасности приходят со значительными затратами. Такие же затраты, вероятно, применимы к Java, но не задумывайтесь об этом, попробуйте что-то там, где производительность критическая. (Кто-нибудь знает о JITed Java, чтобы найти скомпилированную процедуру в памяти? Это, безусловно, возможно)
Ответ 26
Это различие между автоматическими и ручными языками более высокого уровня - это автоматизированные абстракции. C/С++ управляются вручную и обрабатываются, даже код проверки ошибок иногда представляет собой ручной труд.
C и С++ также являются скомпилированными языками, что означает, что ни один из них не работает повсюду в бизнесе, эти языки должны быть точно настроены для оборудования, с которым вы работаете, тем самым добавляя дополнительный уровень getcha. Хотя это немного задумывается, поскольку компиляторы C/С++ становятся все более распространенными во всех платформах. Вы можете выполнять перекрестные компиляции между платформами. Это все еще не работает везде, ваш инструктивный компилятор A компилирует в компилятор B того же кода, что и другая архитектура.
Нижние строки C-языки не должны быть понятны или понятны, поэтому их называют системными языками. Они вышли перед всем этим абстрактом высокого уровня абсурда. Именно поэтому они не используются для веб-программирования на передней панели. Их просто не подходит для этой задачи, их умение решать сложные проблемы, которые невозможно решить с помощью обычного инструментария языка.
Вот почему вы получаете такие сумасшедшие вещи, как (микро-архитектуры, драйверы, квантовая физика, игры AAA, операционные системы), есть вещи, для которых C и С++ хорошо подходят. Скорость и количество хрустов - главные области.
Ответ 27
Даже разница между C и С++ иногда может быть большой.
Когда вы выделяете память для объекта, вызывая конструкторы, выравнивая память на границах слов и т.д., программа завершается, используя множество накладных расходов, которые отвлекаются от программиста.
C заставляет вас взглянуть на каждую вещь, которую делает ваша программа, обычно на очень тонком уровне детализации. Это затрудняет (хотя и не всегда невозможно) код, который выполняет множество задач, которые не нужны для непосредственной цели.
Итак, где, например, в программе BASIC, вы должны использовать ключевое слово INPUT для чтения строковой формы STDIN и автоматически выделять память для своей переменной, в C программист обычно имеет уже выделенную память и может управлять такими вещами, как программа блоки для ввода-вывода или нет, и если он перестает считывать ввод после того, как он имеет нужную ему информацию или продолжает читать символы до конца строки.
C также выполняет намного меньшую проверку ошибок, чем другие языки, предполагая, что программист знает, что они делают. Итак, если в PHP, если вы объявляете строку $myStr = getInput();
и переходите к ссылке $myStr[20]
, но входной файл имеет длину всего 10 символов, PHP поймает это и безопасно вернет вам пустую строку. C предполагает, что вы либо выделили достаточно памяти для хранения данных за концом строки, либо знаете, какая информация появляется после строки, и вместо этого пытается ссылаться на нее. Эти небольшие факторы оказывают огромное влияние на накладные расходы в совокупности.
Ответ 28
Просто выполните машинный код в своей среде IDE, и вы увидите, почему он быстрее (если он быстрее). Он оставляет много рук. Скорее всего, ваш Cxx также может быть заявлен, чтобы он тоже оставил его, и в этом случае он должен быть примерно таким же.
Оптимизация компилятора переоценивается, так как почти все восприятия скорости языка.
Оптимизация сгенерированного кода делает только разницу в коде hotspot, т.е. жесткие алгоритмы, лишенные вызовов функций (явных или неявных). В любом месте он достигает очень мало.
Ответ 29
На самом деле, в некоторых приложениях (численных) даже C может быть избит, и я не имею в виду язык ассемблера, но старый, часто высмеиваемый Fortran. Причина в том, что Fortran не гарантирует сглаживание указателей.