Являются ли статические методы более эффективными?
С точки зрения памяти и времени, лучше ли сделать метод статическим?
Ответы
Ответ 1
Обычно да, нет необходимости передавать ссылку "this". Эта ссылка передается в регистре ECX, поэтому дополнительное пространство стека не требуется. Регистр уже установлен, если вы вызываете вызов из метода экземпляра того же класса, и сэкономить не будет. Но это может помочь уменьшить давление на ядро процессора x86, когда метод находится в другом классе, x86 не имеет большого количества регистров. Увидеть измеримое первичное улучшение было бы чрезвычайно редко.
Я религиозно отмечаю методы класса, которые не используют экземпляры экземпляра как статические. Я оцениваю неотъемлемый контракт, предоставляемый ключевым словом static: "этот метод не мутирует состояние объекта".
Ответ 2
Вы должны сделать метод статическим, если он не требует какой-либо информации о состоянии из класса, в котором он является.
Если вам не нужен полиморфизм, вы можете написать любой метод как экземпляр или статический, просто решив, принимать ли члены экземпляра класса и передавать их методу в качестве аргументов. То, что вы должны учитывать, является ли синтаксис естественным, легко ли он понятен и значим, и т.д.
Вероятно, вам не стоит беспокоиться об оптимизации на этом уровне, поскольку накладные расходы на производительность экземпляра или статического метода незначительны. Да, в таблице диспетчеризации используется тип пространства (если метод виртуальный) - но это крошечные, постоянные накладные расходы. Да, есть и крошечные накладные расходы при вызове метода экземпляра по сравнению с статическим методом, но опять же он крошечный.
Это похоже на уровень микро-оптимизации, что, если у вас нет измеримых, ощутимых доказательств, которые, по нашему мнению, влияют на производительность программы, вам следует избегать. На самом деле, если вы ошибетесь, стоимость передачи дополнительных параметров (копирование их в стек и т.д.) Вместо того, чтобы обращаться к ним с помощью скрытой ссылки this
вашего типа, может привести к ухудшению производительности.
Лучше проанализировать семантику метода и принять на этой основе решение static/instance.
Ответ 3
Если вы все равно пройдете в экземпляре (SomeStaticMethod(obj, "abc", 123);
), то на самом деле. Вы могли бы использовать только статический метод в сценарии без полиморфизма, и в таких случаях очень вероятно, что любые простые вещи, такие как свойства, были бы все равно вложены.
Использовать объекты "естественно" (obj.SomeMethod("abc",123);
) - сохранить код простым и профиль, чтобы найти проблемы с производительностью. очень вряд ли будет в разнице между экземпляр и статический, если вы не используете некоторые очень плотные петли. Есть несколько сценариев, где это может иметь значение, но они довольно специализированы.
Ответ 4
Между статическим методом и не виртуальным методом экземпляров практически нет разницы. Последний просто имеет this
prointer/reference как "скрытый" аргумент. В сгенерированном машинном коде оба вида вызовов выглядят очень похожими.
Метод должен быть статическим, если он не зависит от/не изменяет объект.
Виртуальные методы (overridable), с другой стороны, требуют от вызывающего пользователя поиска точной реализации в так называемом vtable. В дополнение к тому, чтобы компилятор не вставлял очень маленькие методы (простые аксессоры свойств очень часто встраиваются), поиск выполняется за пару циклов.
Тем не менее, виртуальные методы - это самый быстрый вид динамической отправки, доступный в С#/на CLR. Гораздо быстрее, чем делегаты и размышления.
Ответ 5
Есть много вопросов такого рода. Статические методы быстрее/медленнее? Являются ли виртуальные функции более быстрыми/медленными? Является ли я ++ быстрее/медленнее, чем ++ i? Is for (;;) быстрее/медленнее, чем while (true)?
Стоит получить некоторое программное обеспечение и настроить его. Это даст вам хорошее представление о вещах, которые фактически влияют на производительность программного обеспечения на практике.
Затем вы увидите, что ответ на такие вопросы (в большинстве случаев) незначителен.
Если я могу обобщить, то, что делает программное обеспечение медленным, по моему опыту, - это использование строк кода, которые выглядят невиновными, но потребление времени на которые может быть на порядок больше, чем можно представить. Поскольку они выглядят невинно, они не могут быть надежно найдены, просматривая код. Примеры. Неоднократно выделяя, инициализируя и освобождая большие структуры данных, чтобы убедиться, что они существуют. Интернационализация строк, которые не должны быть. Программирование в стиле уведомлений, которое может превратить простую настройку свойства в массивный каскад вызовов методов во всей большой структуре данных. Простые операции O (n ^ 2), которые никогда не были бы проблемой, кроме того, что n было большим. Думая, что (a < b) занимает примерно один и тот же отрезок времени, являются ли a и b int или большими классами. Это "умножение времени, выглядя невиновным" имеет эффект компаундирования по нескольким уровням абстракции, поэтому, по моему опыту, с ним, как правило, искривляется большое программное обеспечение.
Ответ 6
В большинстве случаев разница небрежна, но статичность более эффективна.
В вызове статического метода избегаются следующие шаги:
- Проверка того, что ссылка на объект (это) не является нулевой.
- Поиск правильного метода в таблице виртуальной диспетчеризации.
- Размещение ссылки на объект в стеке.
Ответ 7
Я нахожу, что многие методы утилиты, которые я пишу в пределах данного класса, нуждаются только в нескольких элементах данных в классе или вообще отсутствуют. В этих случаях я склонен писать эти методы как (автономные) статические методы, передавая непосредственно несколько элементов данных, которые им нужны.
Если они являются особенно общими и полезными для других классов, я могу сделать их общедоступными.