Как начать создание поискового сборщика мусора в Delphi (2009-2010) - PullRequest
6 голосов
/ 26 января 2010

Я ищу способ управления всеми бизнес-объектами, которые я создаю в своих приложениях, написанных на Delphi.

Как говорится в статье об EDN Embarcadero (http://edn.embarcadero.com/article/28217)), в основном есть три способа сделать это. Меня больше всего интересует последний, использующий интерфейсы. Таким образом, когда бизнес-объект больше не является ссылка в любом месте приложения будет распоряжаться памятью (я вернусь к этой части позже).

При создании нового бизнес-объекта было бы целесообразно спросить у этого нового менеджера объектов, уже загружал ли я его ранее в программе, чтобы избежать необходимости повторного извлечения его из базы данных. У меня уже есть бизнес-объект в памяти, так почему бы не использовать его? Таким образом, мне понадобится список доступных объектов в памяти для быстрого поиска.

Предоставленный там код использует «массив TObject» для хранения собранных объектов, что не делает его очень производительным в отношении поиска по списку объектов, когда вы получаете определенную сумму. Мне бы пришлось изменить это либо на TObjectList, либо на какое-то двоичное дерево с возможностью поиска. Какой будет лучший выбор здесь? Я уже нашел некоторый полезный код (я думаю) в http://www.ibrtses.com/delphi/binarytree.html. Разве у JCL не было вещей на двоичных деревьях?

Как бы я обработал "бизнес-объекты" и "списки бизнес-объектов" в этом дереве? Будет ли на дерево, являющееся частью списка, дважды ссылаться в дереве?

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

Я также сталкивался с библиотекой Boehm Garbage Collector DLL (http://codecentral.embarcadero.com/Download.aspx?id=21646).

Короче говоря, было бы разумно основывать мой "диспетчер объектов" на исходном коде, представленном в статье EDN? В каком списке я хотел бы хранить свои объекты? Как мне обрабатывать список объектов в моем списке? И следует ли мне еще некоторое время сохранять объект в памяти и распоряжаться им с помощью резьбового монитора?

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

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

Thnx.

Ответы [ 5 ]

3 голосов
/ 26 января 2010

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

То, что вы действительно хотите, это кеш бизнес-объекта. Для этого вы захотите использовать одну из новых универсальных коллекций TDictionary . Что вы можете сделать, это иметь TDictionary из коллекций TDictionary, по одному TDictionary для каждого из ваших типов объектов. Вы можете указать свой основной TDictionary на перечислении или, возможно, даже на типе самого объекта (я не пробовал, но это может сработать.) Если вы используете GUID для своих уникальных идентификаторов, вы можете поместить их все в один TDictionary.

Реализуйте каждый из ваших бизнес-объектов с помощью интерфейса. Вам не нужно использовать Smart Pointers, так как вы проектируете свои бизнес-объекты и можете их потомствовать из TInterfacedObject. Затем ссылаться на него можно только по интерфейсу, чтобы он мог быть подсчитан.

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

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

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

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

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

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

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

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

1 голос
/ 26 января 2010

Для очень быстрого поиска по имени в вашем объекте-контейнере я предлагаю вам смотреть не на деревья, а на хеш-таблицы. Библиотека EZ-DSL (Easy Data Structures) для Delphi включает модуль EHash.pas, который я использую для своих контейнеров хэширования. Если вы заинтересованы в этом, я перешлю его вам.

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

Я также думаю, что вы могли бы сделать так, чтобы объекты сами подсчитали их «полезность», имея поле данных «FLastUsed: Cardinal». Вы можете назначить FLastUsed: = GetTickCount, а затем заставить систему в основном подчиняться установленным вами ограничениям, максимальному количеству памяти или экземпляров, которые будут активно использоваться, и сколько лет объекту (не используемому вообще за X миллисекунд), прежде чем он будет «понижен» до уровня 2, уровня 3 и т. д.

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

1 голос
/ 26 января 2010

Для более высокого уровня я рекомендую две книги: «Шаблоны архитектуры корпоративных приложений» Мартина Фаулера и книгу Эрика Эванса о доменно-управляемом дизайне, «Доменно-управляемый дизайн: решение сложных задач в основе программного обеспечения» (http://dddcommunity.org/books#DDD). Мартин Фаулер объясняет все шаблоны управления объектами для бизнес-приложений, включая репозитории объектов и различные стратегии отображения объектов / баз данных. Книга Эрика Эванса «... предоставляет широкие рамки для принятия проектных решений ...».

Существует несколько библиотек O / R (с открытым исходным кодом) для Delphi с активным сообществом, возможно, их исходный код также может предоставить некоторые технические рекомендации.

1 голос
/ 26 января 2010

Возможно, вы захотите начать с рассмотрения умных указателей. Барри Келли имеет значение для D2009.

Для ваших объектов BI я бы использовал guid в качестве ключевого поля или целое число, уникальное для всей базы данных. Когда вы загружаете объекты в память, вы можете сохранять их в словаре, используя guid в качестве ключа и контейнерный объект в качестве значения.

Контейнерный объект содержит объект bi, ttl и т. Д.

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

0 голосов
/ 26 января 2010

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

Может быть, вы могли бы взглянуть на http://www.danieleteti.it/?p=199 (инверсия шаблонов управления и внедрения зависимостей).

...