Скорость выполнения ссылок против указателей - PullRequest
10 голосов
/ 18 декабря 2008

Недавно я прочитал дискуссию о том, являются ли управляемые языки медленнее (или быстрее), чем родные (особенно C # и C ++). Один из участников дискуссии сказал, что JIT-компиляторы управляемых языков смогут оптимизировать ссылки, что просто невозможно в языках, использующих указатели.

Что я хотел бы знать, это какие виды оптимизации возможны для ссылок, а не для указателей?

Обратите внимание, что речь шла о скорости выполнения, а не об использовании памяти.

Ответы [ 5 ]

10 голосов
/ 18 декабря 2008

В C ++ есть два преимущества ссылок, связанных с аспектами оптимизации:

  1. Ссылка является константой (относится к одной и той же переменной в течение всего времени ее жизни)

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

  2. Предполагается, что ссылка ссылается на что-то (нулевая ссылка отсутствует)

    Ссылка, которая «ссылается на ничто» (эквивалентно указателю NULL), может быть создана, но это не так просто, как создание указателя NULL. По этой причине проверка ссылки на NULL может быть опущена.

Однако ни одно из этих преимуществ не распространяется непосредственно на управляемые языки, поэтому я не вижу актуальности этого в контексте вашей темы для обсуждения.

3 голосов
/ 18 декабря 2008

Вообще говоря, ссылки позволяют ссылаться на один и тот же объект из разных мест.

«Указатель» - это название механизма реализации ссылок. C ++, Pascal, C ... имеют указатели, C ++ предлагает другой механизм (с немного другими случаями использования), называемый 'Reference', но по сути это все реализации общей концепции ссылок.

Так что нет никаких причин, почему ссылки по определению быстрее / медленнее, чем указатели.

Реальная разница заключается в использовании JIT или классического «фронтального» компилятора: данные JIT могут учитывать то, что недоступно для фронтального компилятора. Это не имеет ничего общего с реализацией концепции «ссылка».

3 голосов
/ 18 декабря 2008

Есть некоторые преимущества JIT-компиляции , упомянутые в Википедии:

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

  1. Компиляция может быть оптимизирована для целевого процессора и модели операционной системы, в которой выполняется приложение. Например, JIT может выбрать инструкции процессора SSE2, когда обнаружит, что процессор их поддерживает. При использовании статического компилятора необходимо написать две версии кода, возможно, с использованием встроенной сборки.
  2. Система способна собирать статистику о том, как программа на самом деле работает в среде, в которой она находится, и она может перегруппировать и перекомпилировать для достижения оптимальной производительности. Однако некоторые статические компиляторы также могут принимать информацию профиля в качестве входных данных.
  3. Система может выполнять глобальную оптимизацию кода (например, встраивание функций библиотеки) без потери преимуществ динамического связывания и без накладных расходов, присущих статическим компиляторам и компоновщикам. В частности, при выполнении глобальных встроенных подстановок статический компилятор должен вставлять проверки во время выполнения и обеспечивать выполнение виртуального вызова, если фактический класс объекта переопределяет встроенный метод.
  4. Хотя это возможно для статически скомпилированных языков сборки мусора, система байт-кода может легче переставить память для лучшего использования кэша.

Я не могу думать о чем-то, что напрямую связано с использованием ссылок вместо указателей.

1 голос
/ 18 декабря 2008

Другие ответы верны.

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

0 голосов
/ 16 июля 2013

Ссылка на объект в управляемой среде очень отличается от переданной ссылки в C ++. Чтобы понять, что делает их особенными, представьте, как будет обрабатываться следующий сценарий на уровне компьютера без ссылок на объекты, собираемые мусором: метод «Foo» возвращает строку, которая хранится в разных коллекциях и передается в разные части кода. Если строка больше не нужна, должна быть возможность восстановить всю память, использованную для ее хранения, но неясно, какой фрагмент кода будет последним, который будет использовать строку.

В системе без GC каждая коллекция либо должна иметь свою собственную копию строки, либо должна содержать что-то, содержащее указатель на общий объект, который содержит символы в строке. В последнем случае разделяемый объект должен каким-то образом знать, когда будет удален последний указатель на него. Существует множество способов, которыми это может быть обработано, но существенным общим аспектом всех них является то, что общие объекты должны быть уведомлены, когда указатели на них копируются или уничтожаются. Такое уведомление требует работы.

В отличие от этого, в системе GC программы снабжаются метаданными, указывающими, какие регистры или части стекового фрейма будут использоваться в любой момент времени для хранения корневых ссылок на объекты. Когда происходит цикл сбора мусора, сборщик мусора должен будет проанализировать эти данные, идентифицировать и сохранить все живые объекты и уничтожить все остальное. Однако в любое другое время процессор может копировать, заменять, перемешивать или уничтожать ссылки в любом шаблоне или последовательности, которые ему нравятся, без необходимости уведомлять какие-либо из задействованных объектов. Обратите внимание, что при использовании уведомлений об использовании указателя в многопроцессорной системе, если разные потоки могут копировать или уничтожать ссылки на один и тот же объект, потребуется код синхронизации, чтобы сделать необходимое уведомление безопасным для потока. Напротив, в системе GC каждый процессор может изменять опорные переменные в любое время без необходимости синхронизировать свои действия с любым другим процессором.

...