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

StackOverflow https://stackoverflow.com/questions/202631

Вопрос

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

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

UserController, GeographyController, ShoppingController...

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

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

то есть

ShoppingController.ListPaymentMethods()

вместо

new ShoppingController().ListPaymentMethods()

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

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

Тем не менее, не похоже, что производительность сейчас является вашей самой большой проблемой.

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

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

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

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

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

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

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

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

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

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

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

ПРОТИВ

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, чем средний объектно-ориентированный программист (он полон дерьма, я знаю).

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top