Это широкий вопрос.
По сути, скомпилированные языки переводятся в машинные инструкции (операционные коды) так же, как это делает ASM (ASM также является уровнем абстракции). Хороший компилятор, скорее всего, превзойдет результаты среднего ASM-кодера, потому что он может исследовать большой фрагмент кода и применять правила оптимизации, которые большинство программистов не могут сделать вручную (упорядочение инструкций для оптимального выполнения и т. Д.).
В связи с этим все скомпилированные языки созданы «равными». Однако некоторые более равны, чем другие. Насколько хорошо работает скомпилированный код, в основном зависит от того, насколько хорош компилятор, и гораздо меньше от конкретного языка. Некоторые функции, такие как виртуальные методы, приводят к снижению производительности (в прошлый раз, когда я проверял, виртуальные методы были реализованы с использованием таблицы указателей функций, хотя мои знания могут быть датированы здесь).
Интерпретируемые языки фундаментально исследуют понятный человеку язык во время выполнения программы, по существу требуя эквивалентных стадий компиляции и выполнения во время выполнения программы. Поэтому они почти всегда будут несколько медленнее, чем скомпилированный аналог. Интеллектуальные реализации будут постепенно интерпретировать части кода как выполненные (чтобы избежать интерпретации ветвей, которые никогда не попадут в кэш), и кэшировать результат так, что данная часть кода будет интерпретироваться только один раз.
Также существует золотая середина, в которой читаемый человеком язык переводится в псевдокод (иногда называемый P-кодом или байтовым кодом). Цель этого состоит в том, чтобы иметь компактное представление кода, который быстро интерпретируется, но при этом переносим во многие операционные системы (вам все еще нужна программа для интерпретации P-кода на каждой платформе). Java попадает в эту категорию.