Скорость выполнения ссылок по сравнению с указателями
-
22-08-2019 - |
Вопрос
Недавно я прочитал дискуссию о том, являются ли управляемые языки медленнее (или быстрее), чем родные языки (в частности, C # против C ++).Один человек, участвовавший в обсуждении, сказал, что JIT-компиляторы управляемых языков смогут выполнять оптимизацию в отношении ссылок, которая просто невозможна в языках, использующих указатели.
Что я хотел бы знать, так это какие оптимизации возможны для ссылок, а не для указателей?
Обратите внимание, что обсуждение касалось скорости выполнения, а не использования памяти.
Решение
Есть некоторые преимущества JIT-компиляция упоминается в Википедии:
JIT-код обычно обеспечивает гораздо лучшую производительность, чем интерпретаторы.Кроме того, в некоторых или многих случаях это может обеспечить лучшую производительность, чем статическая компиляция, поскольку многие оптимизации возможны только во время выполнения:
- Компиляция может быть оптимизирована в соответствии с целевым процессором и моделью операционной системы, в которой выполняется приложение.Например, JIT может выбрать инструкции процессора SSE2, когда обнаружит, что процессор их поддерживает.С помощью статического компилятора необходимо написать две версии кода, возможно, используя встроенную сборку.
- Система способна собирать статистику о том, как программа на самом деле выполняется в среде, в которой она находится, и она может изменять порядок действий и перекомпилировать для достижения оптимальной производительности.Однако некоторые статические компиляторы также могут принимать информацию профиля в качестве входных данных.
- Система может выполнять глобальную оптимизацию кода (например,встраивание библиотечных функций) без потери преимуществ динамического связывания и без накладных расходов, присущих статическим компиляторам и компоновщикам.В частности, при выполнении глобальных встроенных замен статический компилятор должен вставлять проверки во время выполнения и гарантировать, что виртуальный вызов произойдет, если фактический класс объекта переопределит встроенный метод.
- Хотя это возможно со статически скомпилированными языками сбора мусора, система байт-кода может более легко перераспределять память для лучшего использования кэша.
Я не могу придумать что-то, связанное непосредственно с использованием ссылок вместо указателей.
Другие советы
В C ++ есть два преимущества ссылок, связанных с аспектами оптимизации:
Ссылка является постоянной (ссылается на одну и ту же переменную в течение всего ее срока службы).
Из-за этого компилятору легче определить, какие имена относятся к одним и тем же базовым переменным, что создает возможности для оптимизации.Нет никакой гарантии, что компилятор будет лучше работать со ссылками, но это возможно...
Предполагается, что ссылка ссылается на что-то (нулевой ссылки нет)
Ссылка, которая "ни на что не ссылается" (эквивалентна нулевому указателю), может быть создана, но это не так просто, как создать нулевой указатель.Из-за этого проверка ссылки на NULL может быть опущена.
Однако ни одно из этих преимуществ не распространяется непосредственно на управляемые языки, поэтому я не вижу значимости этого в контексте вашей темы обсуждения.
В общем, ссылки позволяют ссылаться на один и тот же объект из разных мест.
"Указатель" - это имя механизма для реализации ссылок.C ++, Pascal, C...имея указатели, C ++ предлагает другой механизм (с несколько иными вариантами использования), называемый 'Reference' , но по сути все это реализации общей концепции ссылок.
Таким образом, нет причин, по которым ссылки по определению быстрее / медленнее указателей.
Реальная разница заключается в использовании JIT или классического компилятора "up front":JIT может учитывать данные, которые недоступны для исходного компилятора.Это не имеет никакого отношения к реализации концепции "ссылка".
Другие ответы верны.
Я бы только добавил, что любая оптимизация не будет иметь большого значения, если только она не выполняется в коде, где программный счетчик фактически тратит много времени, например, в узких циклах, которые не содержат вызовов функций (таких как сравнение строк).
Ссылка на объект в управляемой платформе сильно отличается от переданной ссылки в C ++.Чтобы понять, что делает их особенными, представьте, как следующий сценарий был бы обработан на машинном уровне без ссылок на объекты, собираемые мусором:Метод "Foo" возвращает строку, которая хранится в различных коллекциях и передается в разные фрагменты кода.Как только строка больше не понадобится, должна появиться возможность освободить всю память, использованную для ее хранения, но неясно, какой фрагмент кода будет использовать строку последним.
В системе, отличной от GC, каждая коллекция либо должна иметь свою собственную копию строки, либо должна содержать что-то, содержащее указатель на общий объект, который содержит символы в строке.В последней ситуации общий объект должен каким-то образом знать, когда последний указатель на него будет удален.Существует множество способов справиться с этим, но существенным общим аспектом всех из них является то, что общие объекты должны получать уведомления, когда указатели на них копируются или уничтожаются.Такое уведомление требует работы.
В отличие от этого, в системе GC программы украшены метаданными, указывающими, какие регистры или части фрейма стека будут использоваться в любой момент времени для хранения ссылок на корневые объекты.Когда происходит цикл сборки мусора, сборщик мусора должен будет проанализировать эти данные, идентифицировать и сохранить все живые объекты и уничтожить все остальное.Однако в любое другое время процессор может копировать, заменять, перемешивать или уничтожать ссылки в любом шаблоне или последовательности, которые ему нравятся, без необходимости уведомлять какой-либо из задействованных объектов.Обратите внимание, что при использовании уведомлений об использовании указателей в многопроцессорной системе, если разные потоки могут копировать или уничтожать ссылки на один и тот же объект, потребуется код синхронизации, чтобы сделать необходимое уведомление потокобезопасным.Напротив, в системе GC каждый процессор может изменять ссылочные переменные в любое время без необходимости синхронизировать свои действия с каким-либо другим процессором.