Предположим, что программа написана на двух разных языках, пусть это будет язык X и язык Y, если их компиляторы генерируют один и тот же байт-код, почему я должен использовать язык X вместо языка Y? Что определяет, что один язык быстрее, чем другой?
Я спрашиваю об этом, потому что часто вы видите, что люди говорят что-то вроде: «C - самый быстрый язык, ATS - это язык, быстрый как C». Я пытался понять определение «быстрый» для языков программирования.
programming-languages
compilers
Родриго Валенте
источник
источник
Ответы:
Есть много причин, по которым можно выбрать язык X вместо языка Y. Такими причинами могут быть читаемость программы, простота программирования, переносимость на многие платформы, наличие хороших сред программирования. Тем не менее, я буду рассматривать только скорость выполнения, как указано в вопросе. Вопрос, похоже, не учитывает, например, скорость разработки.
Два языка могут компилироваться в один и тот же байт-код, но это не значит, что будет создан один и тот же код,
На самом деле байт-код является только кодом для конкретной виртуальной машины. Он имеет технические преимущества, но не вносит принципиальных отличий в компиляцию для конкретного программного обеспечения. Таким образом, вы могли бы также рассмотреть возможность сравнения двух языков, скомпилированных для непосредственного выполнения на одном компьютере.
Тем не менее, проблема относительной скорости языков является давней, начиная с первых компиляторов.
В течение многих лет, в те ранние времена, профессионалы считали, что рукописный код работает быстрее, чем скомпилированный код. Другими словами, машинный язык считался более быстрым, чем языки высокого уровня, такие как кобол или фортран. И это было быстрее и обычно меньше. Языки высокого уровня все еще развивались, потому что их было намного проще использовать для многих людей, которые не были компьютерными учеными. У стоимости использования языков высокого уровня даже было имя: коэффициент расширения, который мог бы касаться размера сгенерированного кода (очень важная проблема в те времена) или количества фактически выполненных инструкций. Концепция была в основном экспериментальной, но сначала соотношение было больше 1, поскольку по современным стандартам компиляторы проделали довольно простую работу.
Таким образом, машинный язык был быстрее, чем, скажем, Fortran.
Конечно, с годами ситуация изменилась, так как компиляторы стали более сложными, и в настоящее время программирование на языке ассемблера встречается очень редко. Для большинства приложений программы на ассемблере плохо конкурируют с кодом, сгенерированным оптимизирующими компиляторами.
Это показывает, что одной из основных проблем является качество компиляторов, доступных для рассматриваемого языка, их способность анализировать исходный код и соответственно оптимизировать его.
Эта способность может зависеть в некоторой степени от особенностей языка, чтобы подчеркнуть структурные и математические свойства источника, чтобы упростить работу для компилятора. Например, язык может разрешить включение утверждений об алгебраических свойствах пользовательских функций, чтобы компилятор мог использовать эти свойства в целях оптимизации.
Процесс компиляции может быть проще, и, следовательно, производить лучший код, когда парадигма программирования языка ближе к функциям машин, которые будут интерпретировать код, будь то реальная или виртуальная машина.
Другой момент заключается в том, что парадигмы, реализованные в языке, близки к типу программируемой проблемы. Следует ожидать, что язык программирования, специализированный для конкретных парадигм программирования, будет очень эффективно компилировать функции, связанные с этой парадигмой. Следовательно, выбор языка программирования может зависеть, для ясности и скорости, от выбора языка программирования, адаптированного к типу программируемой проблемы.
Популярность C для системного программирования, вероятно, обусловлена тем фактом, что C близок к архитектуре машины, и что системное программирование напрямую связано с этой архитектурой.
Некоторые другие проблемы будут легче программироваться, с более быстрым выполнением с использованием логического программирования и языков разрешения ограничений .
Сложные реактивные системы могут быть очень эффективно запрограммированы с помощью специализированных языков синхронного программирования, таких как Esterel, которые воплощают очень специализированные знания о таких системах и генерируют очень быстрый код.
Или, например, некоторые языки являются узкоспециализированными, например языки описания синтаксиса, используемые для программирования синтаксических анализаторов. Генератор синтаксический анализатор не что иное, как компилятор для таких языков. Конечно, он не является полным по Тьюрингу, но эти компиляторы чрезвычайно хороши для своей специальности: создание эффективных программ синтаксического анализа. Область знаний ограничена, методы оптимизации могут быть очень специализированными и очень точно настроенными. Эти генераторы синтаксических анализаторов обычно намного лучше, чем то, что можно получить, написав код на другом языке. Есть много узкоспециализированных языков с компиляторами, которые производят отличный и быстрый код для ограниченного класса задач.
Следовательно, при написании большой системы может быть целесообразно не полагаться на один язык, а выбирать лучший язык для различных компонентов системы. Это, конечно, поднимает проблемы совместимости.
Другой важный момент - это просто наличие эффективных библиотек для программируемых тем.
Наконец, скорость не является единственным критерием и может вступать в противоречие с другими критериями, такими как безопасность кода (например, при неправильном вводе или устойчивость к системным ошибкам), использование памяти, простота программирования (хотя совместимость парадигмы может действительно помочь этому ), размер объектного кода, сопровождение программы и т. д.
Скорость не всегда самый важный параметр. Также это может принимать разные формы, такие как сложность, которая может быть средней сложности или сложности в худшем случае. Кроме того, в большой системе, как и в небольшой программе, есть части, где скорость имеет решающее значение, и другие, где она не имеет большого значения. И это не всегда легко определить заранее.
источник
Хотя все в конечном итоге выполняется на процессоре * , между разными языками существуют различные различия. Вот несколько примеров.
Интерпретируемые языки Некоторые языки интерпретируются, а не компилируются , например, Python, Ruby и Matlab. Это означает, что код Python и Ruby не компилируется в машинный код, а интерпретируется на лету. Можно скомпилировать Python и Ruby в виртуальную машину (см. Следующий пункт). Смотрите также этот вопрос . Интерпретируется, как правило, медленнее, чем скомпилированный код по разным причинам. Не только сама интерпретация может быть медленной, но и труднее выполнять оптимизацию. Однако, если ваш код тратит большую часть времени на библиотечные функции (в случае Matlab), производительность не пострадает.
Виртуальная машина Некоторые языки компилируются в байт-код , изобретенный «машинный код», который затем интерпретируется. Наиболее существенными примерами являются Java и C #. Хотя байт-код может быть преобразован в машинный код на лету, код, вероятно, будет работать медленнее. В случае Java для переносимости используется виртуальная машина. В случае C # могут быть и другие проблемы, такие как безопасность.
Накладные расходы Некоторые языки обменивают эффективность на безопасность. Например, некоторые версии Pascal проверяют, что вы не обращаетесь к массиву за пределами. Код C # является «управляемым», и это имеет свою стоимость. Другой распространенный пример - сборка мусора, которая экономит время программиста, но не так эффективна, как управление памятью. Существуют и другие источники накладных расходов, такие как инфраструктура для обработки исключений или для поддержки объектно-ориентированного программирования.
* На самом деле, в настоящее время высокопроизводительные системы также выполняют код на графических процессорах и даже на ПЛИС.
источник
Есть разные факторы для выбора X вместо Y, например
Некоторые языки подходят для разработки бизнес-проектов, таких как C # или Python, но, с другой стороны, некоторые из них хороши для системного программирования, например C ++.
Вы должны определить, на какой платформе вы собираетесь работать и какое приложение вы собираетесь создавать.
источник
«Самый быстрый» язык программирования, который вы можете получить на любой платформе, - это язык ассемблера для чипсета, с которым вы работаете. На этом уровне нет переводов. Однако необходимо знать, как чипсет выполняет инструкции, особенно те, которые могут выполнять действия параллельно.
Преобразование из C в сборку очень "мелкое", так как оно близко к одному, но оно более читаемо. Однако он имеет много слоев над ним благодаря стандартным библиотекам для улучшения переносимости. Не так много вещей, которые компилятор должен был бы сделать, чтобы добраться до ассемблерного кода, и более сильные оптимизации обычно вносят изменения, специфичные для машины.
C ++ добавляет более богатый язык. Однако, поскольку язык добавляет столько сложности, компилятору становится все труднее создать оптимальный код для платформы.
Затем мы идем на другую сторону шкалы. Интерпретируемые языки. Они, как правило, самые медленные, потому что помимо выполнения работы, есть некоторое время, затрачиваемое на анализ кода и преобразование его в машинные вызовы.
Тогда у нас есть те между Как правило, они имеют уровень виртуальной машины, оптимизированный для платформы. И компилятор создаст код для виртуальной машины для выполнения. Иногда это происходит одновременно, как perl, pascal, ruby или Python. Или в несколько этапов, как Java.
Некоторые из этих виртуальных машин добавляют понятие JIT-компилятора, который также ускоряет выполнение, создавая код машинного уровня вместо преобразования промежуточного байтового кода.
Некоторые виртуальные машины являются низкоуровневыми, что позволяет меньше переводить из байтового кода в машинный код. Который ускоряет вещи, сохраняя портативность.
источник
*p++=*q++;
бы на многих машинах, был быстрее, чемarray1[i]=array2[i];
на многих процессорах, но часто происходит обратное, и поэтому компиляторы могут в конечном итоге преобразовать первый стиль кода во второй - вряд ли это «поверхностное» преобразование.-O0
это не приведет к оптимизации. Оптимизация - это бонус, который вы получаете с компилятором, но сам по себе язык может переводить почти один в один для сборки.Вопрос, который еще не был упомянут, заключается в том, что в некоторых языках многократное выполнение одного и того же фрагмента кода всегда будет выполнять одну и ту же последовательность действий; Таким образом, компьютеру нужно только один раз определить, что должен делать раздел кода. Одним из основных преимуществ «использования строгого» диалекта JavaScript является то, что, как только механизм JavaScript выясняет, что делает фрагмент кода, он может использовать эту информацию при следующем запуске; без «строгого использования» это невозможно.
Например, в отсутствие «используйте строгий» фрагмент кода, подобный следующему:
может вернуть переменную X в контексте непосредственного вызова, если она есть, или переменную X из внешнего контекста вызова, или она может вернуться
Undefined
. Хуже, в цикле вроде:у движка JavaScript нет возможности узнать, что
g()
может с этим сделатьi
[или сg
самим собой. Посколькуg
илиi
вполне может быть законно преобразованоi
в строку, движок JavaScript не может просто использовать числовое сложение и числовое сравнение в цикле, а должен при каждом проходе цикла проверять, чтобы убедиться, что какой-либо из вызовов функции что-либо сделалi
илиg
, В противоположность этому, на «строгом» [несколько нормальном] диалекте движок JavaScipt может исследовать приведенный выше код и знать, что при каждом прохождении цикла будет использоваться одна и та же числовая переменная и вызываться одна и та же функция. Таким образом, потребуется только определитьi
и функционироватьg
один раз, вместо того, чтобы искать их при каждом прохождении цикла - это значительная экономия времени.источник
Ну, здесь есть несколько довольно профессиональных ответов, они не близки к ним, но могут быть интуитивно понятны для вас.
Возможно, вы много раз слышали, что когда вам нужно выполнить задачу как можно быстрее, вы захотите написать код, который выполняет ее в сборке. Это потому, что вы выполняете только те команды, которые вам действительно нужны для выполнения задачи, и ничего более. В то время как на языке высокого уровня вы могли бы реализовать эту задачу в несколько строк, компилятору все еще нужно перевести их на машинный язык. Этот перевод не всегда минималистичен, так как вы можете написать его напрямую. Это означает, что машина будет тратить много часов на выполнение команд, которые вы можете сэкономить.
Хотя компиляторы сегодня очень сложны, они все еще не эффективны, как это могут делать лучшие программисты на ассемблере.
Продолжая в этом направлении, эти ненужные команды растут в своем количестве (обычно), так как язык более высокоуровневый. (это не на 100% верно для всех языков высокого уровня)
Поэтому для меня язык X быстрее, чем язык Y (во время выполнения), если для определенного фрагмента кода машинный код X короче, чем Y.
источник
На этот вопрос сложно ответить однозначно, потому что он настолько сложный и многомерный (это почти как, например, сравнение марок автомобилей по разным критериям), но существуют новые научные исследования, в том числе превосходное хранилище кодов, известное как код Rosetta ( обзор Википедии ). Этот опрос 2014 года, проведенный Nanz и Furia, изучает этот вопрос довольно точно и научно, основываясь на следующих типичных критериях и редком количественном анализе типично субъективных качеств кода. Аннотация содержит некоторые объективно-обоснованные выводы и обобщения. (Надеюсь, что другие исследования, основанные на этих результатах, могут быть проведены в будущем.)
RQ1. Какие языки программирования делают для более краткого кода?
RQ2. Какие языки программирования компилируются в меньшие исполняемые файлы?
RQ3. Какие языки программирования имеют лучшую производительность во время выполнения?
RQ4. Какие языки программирования используют память более эффективно?
RQ5. Какие языки программирования менее подвержены сбоям?
источник
Компьютерные языки - это просто абстракция команд, объясняющих компьютеру, что делать.
Вы даже можете писать на компьютерном языке
Python
и компилировать его с помощью компилятора C (cython).Учитывая это, скорость компьютерных языков не может сравниться.
Но вы можете сравнить компиляторы для одного и того же языка до некоторой степени. Например,
GNU C
компилятор противIntel C
компилятора. (Поиск по тесту компилятора)источник