Производительность использования статических методов по сравнению с созданием экземпляров класса, содержащего методы - PullRequest
28 голосов
/ 15 октября 2008

Я работаю над проектом на C #. Предыдущий программист не знал объектно-ориентированного программирования, поэтому большая часть кода находится в огромных файлах (мы говорим о 4-5000 строках), распределенных по десяткам, а иногда и сотням методов, но только по одному классу. Рефакторинг такого проекта является огромным делом, и поэтому я уже почти научился жить с ним.

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

Мне интересно, есть ли какие-либо заметные потери производительности при этом? Должен ли я сделать все методы статичными "на данный момент" и, самое главное, получит ли приложение какую-либо выгоду от этого?

Ответы [ 8 ]

25 голосов
/ 15 октября 2008

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

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

9 голосов
/ 25 декабря 2008

Я сталкивался с подобной проблемой, когда работаю. Программист до меня создал 1 класс контроллера, куда были сброшены все функции BLL.

Мы сейчас перерабатываем систему и создали много классов Controller в зависимости от того, что они должны контролировать, например,

UserController, GeographyController, ShoppingController ...

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

Это дало нам 2 основных преимущества. Это немного быстрее (примерно в 2-3 раза быстрее, но мы говорили здесь наносекунды; P). Другое дело, что код намного чище

т.е. 1011 *

ShoppingController.ListPaymentMethods()

вместо

new ShoppingController().ListPaymentMethods()

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

7 голосов
/ 15 октября 2008

Это зависит от того, что еще содержит этот объект - если «объект» - это просто набор функций, то это, вероятно, не конец света. Но если объект содержит кучу других объектов, то создание его экземпляра вызовет все их конструкторы (и деструкторы, когда он будет удален), и вы можете получить фрагментацию памяти и т. Д.

Тем не менее, это не звучит так, как будто производительность - ваша самая большая проблема сейчас.

6 голосов
/ 17 января 2012

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

Очень просто подделывать и / или имитировать объекты, когда вы определяете классы, которые реализуют интерфейсы, и вы выполняете методы экземпляра. Это делает тщательное юнит-тестирование быстрым и эффективным.

Кроме того, если вы хотите следовать хорошим принципам ОО (см. SOLID на http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29) и / или использовать шаблоны проектирования, вы наверняка будете делать много основанных на экземплярах, основанных на интерфейсе разработок и не используя много статических методы.

Что касается этого предложения:

Мне кажется глупым создавать объект ПРОСТО, чтобы вы могли вызывать метод, который казалось бы, не имеет побочных эффектов на объект (из вашего описания я предполагаю это).

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

Помните, что старый каштан, «преждевременная оптимизация - корень всего зла». Я думаю, что в этом случае это означает, что не следует прыгать через обручи, используя неподходящие методы (то есть программирование, ориентированное на класс), пока вы не узнаете, что у вас есть проблемы с производительностью. Даже тогда отлаживайте проблему и ищите наиболее подходящее.

4 голосов
/ 09 ноября 2014

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

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

ShapeUtils.DrawCircle(stroke, pen, origin, radius);

ShapeUtils.DrawSquare(stroke, pen, x, y, width, length);

VS

ShapeUtils utils = new ShapeUtils(stroke,pen);

util.DrawCircle(origin,radius);

util.DrawSquare(x,y,width,length);

В этом случае, когда переменные экземпляра используются всеми методами большую часть времени, методы экземпляра того стоят. Экземпляры не о состоянии, речь идет об обмене, хотя ОБЩЕЕ СОСТОЯНИЕ является естественной формой обмена, они НЕ ТО ЖЕ. Общее эмпирическое правило таково: если метод тесно связан с другими методами - они так сильно любят друг друга, что при вызове одного из них нужно вызывать и другого, и они, вероятно, делят одну и ту же чашку воды - - следует сделать экземпляр. Переводить статические методы в методы экземпляров не так сложно. Вам нужно только взять общие параметры и поместить их в качестве переменных экземпляра. Обратный путь сложнее.

Или вы можете создать прокси-класс, который будет связывать статические методы. Хотя это может показаться более неэффективным в теории, практика рассказывает другую историю. Это потому, что всякий раз, когда вам нужно вызвать DrawSquare один раз (или в цикле), вы переходите прямо к статическому методу. Но всякий раз, когда вы будете использовать его снова и снова вместе с DrawCircle, вы будете использовать прокси экземпляра. Примером являются классы System.IO FileInfo (экземпляр) против File (статический).

Статические методы являются тестируемыми. На самом деле, даже более проверяемый, чем экземпляр раз. Метод GetSum (x, y) был бы очень тестируемым не только для модульного теста, но и для нагрузочного теста, интегрированного теста и теста использования. Методы экземпляра хороши для юнит-тестов, но ужасны для любых других тестов (что важнее, чем юнит-тесты, кстати), поэтому в наши дни мы получаем так много ошибок. То, что делает ВСЕ Методы непроверяемыми, это параметры, которые не имеют смысла, например (Sender s, EventArgs e) или глобальное состояние, например DateTime.Now. На самом деле статические методы настолько хороши в тестируемости, что вы видите меньше ошибок в коде C нового дистрибутива Linux, чем ваш обычный программист OO (он полон s ***, я знаю).

3 голосов
/ 15 октября 2008

Я думаю, что вы частично ответили на этот вопрос так, как задали его: есть ли заметные потери производительности в вашем коде?

Если штрафы не заметны, вам вовсе не обязательно ничего делать. (Хотя само собой разумеется, что кодовая база извлечет выгоду из постепенного рефакторинга в респектабельную модель ОО).

Полагаю, я говорю о том, что проблема с производительностью - это проблема, только когда вы замечаете, что это проблема.

2 голосов
/ 15 октября 2008

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

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

Опять же, подход, который I , вероятно, использовал бы иначе;).

Лично я бы, скорее всего, сосредоточился на структурах и функциях, которые над ними работали, и попытался бы постепенно преобразовать их в классы с членами.

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

0 голосов
/ 03 апреля 2015

Это не действует в PHP,
Метод объекта быстрее:
http://www.vanylla.it/tests/static-method-vs-object.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...