Подтвердить что ты не робот

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

Если С#, Java или С++, например, все компилируются в машинный код, почему они не одинаково эффективны?

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

4b9b3361

Ответ 1

С одной стороны, оптимизаторы С++ гораздо более зрелые. Еще одна, производительность всегда была главной целью разработчиков языка С++ ( "вы не платите за то, что не используете" ) - это мантра, о которой явно нельзя сказать о Java-методе "все-метод-есть-виртуальная" ).

Кроме того, шаблоны С++ гораздо более оптимизированы, чем Java или С# generics. Хотя JIT часто хвалили за их способность оптимизировать границы модулей, дженерики останавливают этот мертвый по своим следам. CLR (среда выполнения .NET) генерирует только одну версию машинного кода для общего типа, который охватывает все ссылочные типы. С другой стороны, оптимизатор С++ запускается для каждой комбинации параметров шаблона и может встраивать зависимые вызовы.

Далее, с С# и Java у вас очень мало контроля над макетом памяти. Параллельные алгоритмы могут пострадать на порядок ухудшения производительности от ложного обмена линиями кеша, и почти ничего, что разработчик может сделать с этим. OTOH С++ предоставляет инструменты для размещения объектов при определенных смещениях относительно страниц ОЗУ и границ кэша.

Ответ 2

Учитывайте различия в языках и накладных расходах, даже если такая дополнительная работа выполняется "с той же эффективностью", что нужно сделать еще больше. Период. (Это цена, которая часто встречается с абстракцией: время разработки может [существенно] уменьшаться для [умеренных] увеличений во время выполнения.)

С другой стороны, с тривиальной функцией, не использующей "языковых функций", таких как цикл, вычисляющий факторный... тогда числа могут стать очень конкурентоспособными в некоторых случаях. Это можно увидеть в Компьютерная игра Benchmark Game (здесь Java7 против С++).

Обратите внимание, что реализация языка (включая JIT) и применяемых оптимизаций ( "-Ox" ) также является основным фактором. (Язык, возможно, "не имеет скорости" сам по себе.)

Счастливое кодирование.


Как отметил Фойгт, модели JIT/AOT оптимизированы для разных аспектов. (Реализация Oracle Java Sun даже имеет отдельную виртуальную машину VM и клиентскую виртуальную машину, каждая из которых определяет приоритетные варианты использования.) Ниже приведены некоторые сообщения SO, обсуждающие JIT vs. AOT:

Ответ 3

"Если С#, Java или С++, например, все в конечном итоге компилируются в машинный код, почему они не одинаково эффективны?"

Оба С# и Java компилируются в байт-код, который в конечном итоге сводится к машинным кодам с помощью виртуальной машины (например, для Java, называемой JVM). С++, однако, обычно скомпилирован до уровня сборки.

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

Ответ 4

Знаете ли вы, что тот же код на С++ не создает один и тот же машинный код с разными компиляторами или разными версиями одного и того же компилятора? Некоторые компиляторы будут использовать один и тот же источник и создать двоичный файл для той же цели, что значительно быстрее, чем другой компилятор. По тем же причинам другие языки, которые компилируются в машинный код, не будут работать одинаково. Некоторые языки легче компилировать/оптимизировать, чем другие. Языки, подобные Java, не сравниваются, поскольку они не компилируются в машинный код, который они обычно компилируют в системный независимый байт-код, а затем запускаются на виртуальной машине jvm. jvm - некоторый код на некотором языке, скомпилированный некоторым компилятором, который может быть быстрым или медленным в зависимости от выбранного кода и компилятора. интерпретируемые языки, такие как java (байт-код), медленны по сравнению с компиляцией непосредственно в машинный код.

Потратьте некоторое время, чтобы узнать, как разбирать исполняемые файлы, которые вы скомпилировали. Прочитайте инструкции инструкций типа байт-кода за java, python и т.д. P-код, который использовался pascal и т.д. И т.д.

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

Ваш вопрос похож на вопрос, если у всех автомобилей в основном есть двигатель и четыре колеса, почему некоторые могут двигаться быстрее? Почему некоторые могут перетаскивать больше, чем другие?

Ответ 5

Если С#, Java или С++, например, все в конечном итоге компилируются на машину код, почему они не одинаково эффективны?

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

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

Например, Фрезел указал на измерения крошечной программы умножения, и эти измерения были следующими:

  • сделанный с Java 1.4 в 2003 году, - текущая версия - это Java 7

  • сделано очень наивно, что помешало Java завершить сборник

Позвольте просто запустить его программу полдюжины раз без повторного запуска JVM и посмотреть, что произойдет:

public class mult {

    public static void main(String[] args){
        for (int i=0; i<6; ++i) mult.program_main(args);
   }

    public static void program_main(String[] args) {
        long nbStep = 1000000000;
        long tCPU = System.currentTimeMillis();
        double t=1. , r= 0.9999999999999999999999999999999999;

        if ( args.length > 0 ) {
            nbStep = Integer.parseInt(args[0]);
            System.out.println( args[0] + " demandees" );
        }
        for ( long i = 0; i < nbStep; i++ ) {
            t = t * r;
        }
        tCPU = - tCPU + System.currentTimeMillis();
        System.out.println(nbStep + " multiplications en " +
            tCPU + " millisecondes ." );
    }
}


$ /usr/local/src/jdk1.7.0/bin/java -XX:+PrintCompilation -XX:+PrintGC mult
     53    1 %           mult::program_main @ 57 (122 bytes)
   4662    1 %           mult::program_main @ -2 (122 bytes)   made not entrant
1000000000 multiplications en 4609 millisecondes .
   4662    1             mult::program_main (122 bytes)
   4669    2 %           mult::program_main @ 57 (122 bytes)
1000000000 multiplications en 4612 millisecondes .
1000000000 multiplications en 564 millisecondes .
1000000000 multiplications en 563 millisecondes .
1000000000 multiplications en 563 millisecondes .
1000000000 multiplications en 563 millisecondes .

Когда Java завершает компиляцию, время падает с 4609ms до 563ms.

Код Java в 8 раз быстрее, чем можно было бы предположить наивное измерение.