IMO да, но по фундаментальной причине проектирования, гораздо более тонкой и сложной, чем запросы виртуальной диспетчеризации или COM-подобные интерфейсы или метаданные объекта, необходимые для информации о типе среды выполнения или чего-либо подобного. Все это связано с накладными расходами, но во многом зависит от используемого языка и компилятора (ов), а также от того, может ли оптимизатор устранить такие издержки во время компиляции или компоновки. Тем не менее, по моему мнению, существует более широкая концептуальная причина, по которой кодирование интерфейса подразумевает (а не гарантирует) снижение производительности:
Кодирование интерфейса подразумевает наличие барьера между вами и
конкретные данные / память, к которым вы хотите обращаться и преобразовывать.
Это основная причина, которую я вижу. В качестве очень простого примера, скажем, у вас есть интерфейс абстрактного изображения. Он полностью абстрагирует свои конкретные детали, такие как формат пикселей. Проблема здесь в том, что часто наиболее эффективные операции с изображениями нуждаются в этих конкретных деталях. Мы не можем реализовать наш пользовательский фильтр изображений с эффективными инструкциями SIMD, например, если нам нужно было getPixel
по одному за раз и setPixel
по одному за раз, не обращая внимания на основной формат пикселей.
Конечно, абстрактное изображение может пытаться обеспечить все эти операции, и эти операции могут быть реализованы очень эффективно, поскольку они имеют доступ к частным, внутренним деталям конкретного изображения, которое реализует этот интерфейс, но это сохраняется только до тех пор, пока поскольку интерфейс изображения предоставляет все, что клиент когда-либо хотел бы сделать с изображением.
Часто в какой-то момент интерфейс не может надеяться предоставить все функции, которые можно вообразить всему миру, и поэтому такие интерфейсы, когда сталкиваются с проблемами производительности и одновременно нуждаются в выполнении широкого спектра потребностей, часто будут пропускать свои конкретные детали. , Абстрактное изображение может по-прежнему предоставлять, скажем, указатель на свои базовые пиксели с помощью метода pixels()
, который в значительной степени устраняет многие цели кодирования интерфейса, но часто становится необходимостью в наиболее критичных для производительности областях.
Как правило, на каком-то уровне часто приходится писать наиболее эффективный код на основе конкретных деталей, например, код, написанный специально для плавающей запятой одинарной точности, код, написанный специально для 32-битных изображений RGBA, код, написанный специально для графического процессора, специально для AVX-512, специально для мобильного оборудования и т. д. Таким образом, существует фундаментальный барьер, по крайней мере с имеющимися у нас инструментами, где мы не можем абстрагироваться от всего этого и просто кодировать интерфейс без подразумеваемых штрафов .
Конечно, наша жизнь стала бы намного проще, если бы мы могли просто написать код, не обращая внимания на все такие конкретные детали, как, например, имеем ли мы дело с 32-битным SPFP или 64-битным DPFP, пишем ли мы шейдеры на ограниченное мобильное устройство или высококлассный рабочий стол, и все это должно быть наиболее конкурентоспособным кодом. Но мы далеки от этой стадии. Наши современные инструменты все еще часто требуют от нас написания кода, критичного к производительности, с учетом конкретных деталей.
И, наконец, это своего рода проблема гранулярности. Естественно, если нам придется работать с вещами на попиксельной основе, то любые попытки абстрагироваться от конкретных деталей пикселя могут привести к значительному снижению производительности. Но если мы выражаем вещи на уровне изображений, например, «альфа-смешение этих двух изображений», это может быть очень незначительной стоимостью, даже если есть виртуальные накладные расходы и так далее. Поэтому, когда мы работаем над кодом более высокого уровня, зачастую любое подразумеваемое снижение производительности при кодировании для интерфейса уменьшается до такой степени, что становится совершенно тривиальным. Но всегда есть потребность в низкоуровневом коде, который выполняет такие вещи, как обработка вещей на попиксельной основе, повторяя миллионы из них много раз за кадр, и там стоимость кодирования интерфейса может нести довольно существенный штраф, хотя бы потому, что он скрывает конкретные детали, необходимые для написания наиболее эффективной реализации.