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





Есть некоторые преимущества JIT-компиляция, упомянутые в Википедии:
JIT code generally offers far better performance than interpreters. In addition, it can in some or many cases offer better performance than static compilation, as many optimizations are only feasible at run-time:
- The compilation can be optimized to the targeted CPU and the operating system model where the application runs. For example JIT can choose SSE2 CPU instructions when it detects that the CPU supports them. With a static compiler one must write two versions of the code, possibly using inline assembly.
- The system is able to collect statistics about how the program is actually running in the environment it is in, and it can rearrange and recompile for optimum performance. However, some static compilers can also take profile information as input.
- The system can do global code optimizations (e.g. inlining of library functions) without losing the advantages of dynamic linking and without the overheads inherent to static compilers and linkers. Specifically, when doing global inline substitutions, a static compiler must insert run-time checks and ensure that a virtual call would occur if the actual class of the object overrides the inlined method.
- Although this is possible with statically compiled garbage collected languages, a bytecode system can more easily rearrange memory for better cache utilization.
Я не могу придумать ничего, связанного непосредственно с использованием ссылок вместо указателей.
Одно конкретное доказательство большого проекта было сделано с помощью IronPython vs CPython. Последние версии IronPython превосходят CPython во всех тестах с небольшим или большим отрывом, сохраняя при этом 100% совместимость. Это с учетом нескольких лет оптимизации CPython и молодого проекта IronPython.
Вы не ответили на вопрос ... «Я хотел бы знать, какие оптимизации возможны для ссылок, а не для указателей?» ...
Я думаю, что суть вопроса может быть основана на предположениях о том, как ссылки и указатели используются на практике (ваша ссылка на конкретный объект? Ваш указатель просто на недействительность?) В отличие от всего, что связано с тем, как они работают.
В C++ есть два преимущества ссылок, связанных с аспектами оптимизации:
Ссылка постоянна (относится к одной и той же переменной в течение всего ее срока службы)
Из-за этого компилятору легче определить, какие имена относятся к одним и тем же базовым переменным, что создает возможности для оптимизации. Нет никакой гарантии, что компилятор будет лучше справляться со ссылками, но он может ...
Предполагается, что ссылка ссылается на что-то (нет нулевой ссылки)
Ссылка, которая «ни на что не ссылается» (эквивалент NULL-указателя), может быть создана, но это не так просто, как создание NULL-указателя. По этой причине проверку ссылки на NULL можно не проводить.
Однако ни одно из этих преимуществ не распространяется непосредственно на управляемые языки, поэтому я не вижу актуальности этого в контексте вашей темы обсуждения.
В общем, ссылки позволяют ссылаться на один и тот же объект из разных мест.
«Указатель» - это название механизма для реализации ссылок. C++, Pascal, C ... имеют указатели, C++ предлагает другой механизм (с немного другими вариантами использования), называемый «Ссылка», но, по сути, все это реализации общей концепции ссылок.
Таким образом, нет причин, по которым ссылки по определению быстрее / медленнее, чем указатели.
Реальная разница заключается в использовании JIT или классического «предварительного» компилятора: JIT может учитывать данные, которые недоступны для предварительного компилятора. Это не имеет ничего общего с реализацией понятия «ссылка».
Другие ответы верны.
Я бы только добавил, что любая оптимизация не будет иметь большого значения, если только она не находится в коде, где счетчик программы действительно тратит много времени, например, в жестких циклах, которые не содержат вызовов функций (например, сравнение строк).
Ссылка на объект в управляемой платформе сильно отличается от переданной ссылки в C++. Чтобы понять, что делает их особенными, представьте, как будет обрабатываться следующий сценарий на уровне машины без ссылок на объекты, собранные сборщиком мусора: Метод «Foo» возвращает строку, которая сохраняется в различных коллекциях и передается в разные части кода. Если строка больше не нужна, появится возможность вернуть всю память, используемую для ее хранения, но неясно, какой фрагмент кода будет последним, который будет использовать строку.
В системе, отличной от GC, каждая коллекция либо должна иметь свою собственную копию строки, либо должна содержать что-то, содержащее указатель на общий объект, который содержит символы в строке. В последней ситуации общий объект должен каким-то образом знать, когда последний указатель на него будет удален. Есть множество способов справиться с этим, но важным общим аспектом всех из них является то, что общие объекты необходимо уведомлять, когда указатели на них копируются или уничтожаются. Такое уведомление требует доработки.
Напротив, в системе GC программы украшены метаданными, чтобы указать, какие регистры или части кадра стека будут использоваться в любой момент времени для хранения ссылок на корневые объекты. Когда происходит цикл сборки мусора, сборщик мусора должен проанализировать эти данные, идентифицировать и сохранить все живые объекты и уничтожить все остальное. Однако в остальное время процессор может копировать, заменять, перемешивать или уничтожать ссылки в любом шаблоне или последовательности, которые ему нравятся, без необходимости уведомлять какие-либо задействованные объекты. Обратите внимание, что при использовании уведомлений об использовании указателя в многопроцессорной системе, если разные потоки могут копировать или уничтожать ссылки на один и тот же объект, потребуется код синхронизации, чтобы сделать необходимое уведомление потокобезопасным. Напротив, в системе GC каждый процессор может изменять ссылочные переменные в любое время без необходимости синхронизировать свои действия с любым другим процессором.
Что ж, если вы неправильно управляете памятью, это, безусловно, может снизить скорость выполнения.