Каковы последствия производительности методов выделения / свойства как виртуальные?

Начиная с 2013 года, если вы используете facebook.com/sharer.php (PHP), вы можете просто создать любую кнопку / ссылку, например:

<a class="btn" target="_blank" href="http://www.facebook.com/sharer.php?s=100&amp;p[title]=<?php echo urlencode(YOUR_TITLE);?>&amp;p[summary]=<?php echo urlencode(YOUR_PAGE_DESCRIPTION) ?>&amp;p[url]=<?php echo urlencode(YOUR_PAGE_URL); ?>&amp;p[images][0]=<?php echo urlencode(YOUR_LINK_THUMBNAIL); ?>">share on facebook</a>

Параметры запроса ссылки:

p[title] = Define a page title
p[summary] = An URL description, most likely describing the contents of the page
p[url] = The absolute URL for the page you're sharing 
p[images][0] = The URL of the thumbnail image to be used as post thumbnail on facebook

Это просто: вам не нужны никакие js или другие настройки. Это всего лишь HTML-ссылка. Создайте тег A любым способом, который вы хотите.

63
задан Erik Forbes 10 February 2009 в 01:49
поделиться

7 ответов

Виртуальные функции только имеют очень маленькую производительность наверху по сравнению с прямыми вызовами. На низком уровне Вы в основном смотрите на поиск массива для получения указателя функции и затем вызова через указатель функции. Современные центральные процессоры могут даже предсказать косвенные вызовы функции обоснованно хорошо в их предикторах ответвления, таким образом, они обычно не будут повреждать современные конвейеры ЦП слишком ужасно. На уровне ассемблера вызов виртуальной функции переводит во что-то как следующее, где I произвольное непосредственное значение.

MOV EAX, [EBP + I] ; Move pointer to class instance into register
MOV EBX, [EAX] ;  Move vtbl pointer into register.
CALL [EBX + I]  ;   Call function

По сравнению со следующим для прямого вызова функции:

CALL I  ;  Call function directly

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

Редактирование: Другая вещь иметь в виду состоит в том, что все программы требуют управления потоком, и это никогда не свободно. Что заменило бы Вашу виртуальную функцию? Оператор переключения? Ряд если операторы? Это все еще ответвления, которые могут быть непредсказуемыми. Кроме того, учитывая N-путь ответвление, серия того, если операторы найдут надлежащий путь в O (N), в то время как виртуальная функция найдет его в O (1). Оператор переключения может быть O (N) или O (1) в зависимости от того, оптимизирован ли он к таблице переходов.

139
ответ дан dsimcha 7 November 2019 в 12:28
поделиться

Rico Mariani обрисовывает в общих чертах проблемы относительно производительности в его блог Лакомых кусочков Производительности, где он заявил:

Виртуальные Методы: Вы использующий виртуальные методы, когда прямые вызовы сделали бы? Много раз люди идут с виртуальными методами для обеспечения будущей расширяемости. Расширяемость является хорошей вещью, но она действительно прибывает в цену †“, удостоверяются, что Ваша полная история расширяемости разработана и что Ваше использование виртуальных функций на самом деле собирается получить Вас туда, где необходимо быть. Например, иногда люди продумывают проблемы сайта вызова, но затем don’t рассматривают, как объекты “extended” будут созданными. Позже они понимают, что (большая часть) виртуальные функции didn’t помогают вообще, и им была нужна совершенно другая модель для получения объектов “extended” в систему.

Изоляция: Изоляция может быть способом ограничить полиморфизм Вашего класса на просто те сайты, где полиморфизм необходим. Если Вы будете полностью управлять типом, затем изолирующим, может быть большая вещь для производительности, поскольку это включает прямые вызовы и встраивание.

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

В статье MSDN, Улучшающей Производительность приложения.NET и Масштабируемость , это далее разъяснено:

Полагают, что Компромиссы Виртуальных участников

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

критика А вышеупомянутого, однако, прибывает из лагеря TDD/BDD (кто хочет методы, принимающие значение по умолчанию к виртуальному), утверждающий, что влияние производительности незначительно так или иначе, тем более, что мы получаем доступ к намного более быстрым машинам.

16
ответ дан Jon Limjap 7 November 2019 в 12:28
поделиться

Обычно виртуальный метод просто проходит один table-of-function-pointers для достижения фактического метода. Это означает, что одно дополнительное разыменовывает и еще одно распространение в прямом и обратном направлениях к памяти.

, В то время как стоимостью не является абсолютно НУЛЬ, это чрезвычайно минимально. Если помогает, что Ваша программа вообще, чтобы иметь виртуальные функции, любой ценой, делает это.

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

11
ответ дан abelenky 7 November 2019 в 12:28
поделиться

я запустил этот тест в C++ . Вызов виртуальной функции берет (на PowerPC на 3 ГГц) между 7-20 наносекундами дольше, чем прямой вызов функции. Это означает, что действительно только имеет значение для функций, Вы планируете на вызове миллион раз в секунду, или для функций, которые являются столь небольшими, что издержки могут быть больше, чем сама функция. (Например, делание функций средства доступа, виртуальных из слепой привычки, вероятно, неблагоразумно.)

я не запустил свой тест в C#, но я ожидаю, что различие будет еще меньше там, так как почти каждая операция в CLR включает косвенное так или иначе.

3
ответ дан Crashworks 7 November 2019 в 12:28
поделиться

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

, статический метод А будет связан во время компиляции. Виртуальный метод требует, чтобы поиск во времени выполнения решил который метод звонить, таким образом, существуют маленькие издержки. Только значительно, если метод является маленьким и часто назван.

3
ответ дан Richard A 7 November 2019 в 12:28
поделиться

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

[Как интересный факт, на компактной версии 1.0 платформы перегревание больше, поскольку это не использует таблицы виртуальных методов, но просто отражение, чтобы обнаружить, что правильный метод выполняется при вызове виртуального метода.]

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

Примерно это - иерархия производительности вызовов метода:

Не виртуальные методы < Виртуальный Metods < Методы интерфейса (на классах) < отправка Делегата < MethodInfo. Вызовите < Ввести. InvokeMember

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

0
ответ дан Pop Catalin 7 November 2019 в 12:28
поделиться

Трудно сказать наверняка, потому что JIT-компилятор.NET может оптимизировать издержки далеко в некоторых (многие?) случаи.

, Но если это не оптимизирует его далеко, мы в основном говорим о дополнительной косвенности указателя.

таким образом, при вызове невиртуального метода Вы имеете к

  1. , Сохраняют регистры, генерируют пролог функции / эпилог, чтобы настроить аргументы, скопировать возвращаемое значение и такой.
  2. переход к фиксированному, и статически известный, обратитесь

1, то же в обоих случаях. Что касается 2, с виртуальным методом, необходимо вместо этого читать из фиксированного смещения в vtable объекте, и затем перейти к тому, везде, где это указывает. Это делает предсказание ветвлений тяжелее, и оно может продвинуть некоторые данные из кэша ЦП. Таким образом, разница не огромна, но она может сложить при создании каждого вызова функции виртуальным.

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

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

4
ответ дан jalf 7 November 2019 в 12:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: