Оптимизировать объекты с различными свойствами - PullRequest
2 голосов
/ 21 декабря 2011

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

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

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

Какое решение является более оптимизированным? Имеет ли смысл создавать несколько версий классов? Что делать, если ненужные свойства просто остаются нулевыми? Является ли объект с нулевыми (неназначенными) свойствами тяжелее, чем тот же, без этих свойств?

Большое спасибо за ваши ответы!

Ответы [ 2 ]

1 голос
/ 21 декабря 2011

Я не уверен, что это поможет вам конкретно в вашей проблеме, но в .NET 4.0 появился класс Lazy , который представляет собой класс-оболочку, используемый для отложенной инициализации экземпляров тяжелых / больших объектов.Он предлагает свойство .Value, которое при обращении в первый раз (и только в первый раз) инициализирует экземпляр обернутого объекта.Если к .Value никогда не осуществляется доступ, обертываемый экземпляр объекта никогда не инициализируется.Но похоже, что вы уже делаете это сами, скорее всего, в своем определении Get / Set.

С точки зрения того, какой объект тяжелее, легкий класс без свойств или исходный класс с переменными NULL.: Если свойства в вопросах являются ссылочными типами, то единственная потеря - это указатель на ссылочный тип, который составляет 4 байта на свойство для x86 и 8 байтов на свойство для x64.Минимальный размер по умолчанию для пустого экземпляра класса в .NET составляет около ~ 24 байт.

Например:

public class MyClassLight
{
    public int PropertyInt { get; set; } // 4 byte value type
    public OtherClass1 PropertyOtherClass1 { get; set; } // 4 or 8 byte reference type
}

public class MyClassHeavy
{
    public int PropertyInt { get; set; } // 4 byte value type
    public string PropertyString { get; set; } // 4 or 8 byte reference type
    public OtherClass1 PropertyOtherClass1 { get; set; } // 4 or 8 byte reference type
    public OtherClass2 PropertyOtherClass2 { get; set; } // 4 or 8 byte reference type
}

Допустим, вы запускали на x86 экземпляр MyClassLightбудет стоить 24 байта + 4 байта + 4 байта = 32 байта памяти.

MyClassHeavy будет 24 байта + 4 байта + 4 байта + 4 байта + 4 байта = 40 байтов памяти.

Даже если у вашего тяжелого класса было 50 свойств, которые являлись ссылочными типами, сохранение их в NULL потребовало бы дополнительных 200 байт памяти на экземпляр (поскольку классу все еще нужно резервировать память для указателей, которые могут использоваться в некоторых случаях).точка).Если у вас есть сотни тысяч или миллионы этих объектов в памяти, 200 байт на объект могут быть проблемой, но если нет, то это кажется незначительным.

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

0 голосов
/ 21 декабря 2011

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

...