1. Непосредственные факторы. Каждый раз, когда вы создаете объект, перед его использованием должна быть распределена и инициализирована память. Это прямые предварительные расходы, которые должен оплатить ваш алгоритм.
2. Косвенные факторы. После того как приложение освободило объект, он становится "мусором" Этот мусор накапливается в приложении, пока его не соберется так много, что для последующего распределения памяти для новых объектов потребуется ее предварительная очистка от старых. Конечно же, именно это и называется сборкой мусора. На сборку мусора уходит определенное время, и если мусора много, то эта операция заметно затормозит работу вашего приложения. Чем больше вы сорите, тем больше накапливается мусора и тем чаще приходится тратить время на уборку!
В процессе программирования вы всегда должны стараться "сорить" как можно меньше. Нет ничего плохого в том, чтобы создать экземпляр объекта, если это помогает решить какую-то очень важную задачу; если же объект является короткоживущим и задача может быть решена без него, то вы только создаете мусор. Не будьте "неряхой"!
"Структуры" и .NET Compact Framework
Во многих случаях, если вы хотите инкапсулировать некоторые простые данные, то для локальных переменных внутри функций гораздо эффективнее использовать не объекты, а структуры. Структура — это просто удобный способ сгруппировать в одном пакете взаимосвязанные данные, а не передавать их в виде отдельных переменных.
Структуры обладают более простыми свойствами по сравнению с объектами, но могут "упаковываться" в объекты и передаваться внутри программы так же, как они, если в этом возникает необходимость. Использование структур предоставляет определенные удобства и может привести к некоторому увеличению производительности (по сравнению с вариантом, когда используются объекты), но поскольку они выглядят, а во многих случаях и действуют подобно объектам и могут заключаться в объекты-оболочки, необходимо тщательно взвешивать, когда их следует использовать, чтобы избежать дополнительных накладных расходов и не создать лишнего мусора. В сомнительных случаях тестируйте алгоритмы, используя как отдельные переменные (например, базовые типы, подобные int, string, double), так и структуры, чтобы сравнить производительность приложения в обоих случаях и убедиться в том, что она остается примерно одинаковой.
Более подробную информацию по этому вопросу вы можете получить, обратившись к разделам справочной документации .NET Compact Framework, посвященным типам значений ("value types") и структурам ("struct"). Ниже приводится пример с объявлениями структуры и класса:
//Примечание. В VB.NET это был бы тип (type), а не структура (struct)
//Это структура
struct MyRect_Type {
public int x;
public int у;
}
//Это класс
class MyRect_Class {
public int x;
public int у;
}
//Код примера
class TestClass {
public void foo() {
//Требуется распределять как объект
MyRect_Class myRectClass = new MyRect_Class();
myRectClass.x = 1;
myRectClass.y = 2;
//Этот оператор распределяет новый объект
myRectClass = new MyRect_Class();
//Можно объявить как скалярный тип
MyRect_Type myRectType;
myRectType.x = 1;
myRectType.y = 2;
//Этот оператор обнуляет значения в структуре, но не
//распределяет память для нового объекта!
myRectType = new MyRect_Type();
}
Пишите экономные алгоритмы: разумно расходуйте память и повторно используйте объекты
Представленный ниже пример иллюстрирует несколько различных вариантов реализации одного и того же базового алгоритма. Алгоритм предназначен для обработки массива строк. Каждая строка в массиве состоит из трех частей, разделенных символом подчеркивания (например, big_shaggy_dog). Алгоритм предполагает просмотр каждого из элементов массива и проверку того, не является ли его средняя часть словом blue (например, my_blue_car). Если это так, то слово blue заменяется словом orange (например, my_blue_car становится my_orange_car).
Кроме того, в каждом из описанных алгоритмов используется вспомогательный класс, упрощающий разбиение строк и получение данных, содержащихся в каждом из трех сегментов. Первый алгоритм (листинги 8.3 и 8.4) представляет собой некое разумное первое приближение, а следующие два алгоритма (листинги 8.5 и 8.6 и листинги 8.7 и 8.8) — его оптимизированные варианты, улучшающие первоначальную тактику. Целью оптимизации являлось непосредственное улучшение производительности, а также уменьшение количества "мусора", вырабатываемого каждым из алгоритмов.
Читать дальше