5. Потоковые хранилища
Очень часто во многих программах встает проблема накопления потока поступающих данных. Например, это может быть запись звука, запись сигналов с датчиков, накопление данных с модема, коммуникационного порта, прием данных по сети и так далее. Если объем накапливаемых данных небольшой и заранее точно известен, то такая задача решается элементарно - под буфер выделяется блок памяти и эта память постепенно заполняется. Если же размер требуемого буфера достаточно большой, то выделение его полностью в самом начале может быть неэффективным - запись потока может прерваться гораздо раньше, а если же размер его неизвестен заранее, например когда запись данных останавливается по какому-либо внешнему сигналу, то встает проблема о выборе размера выделяемого блока.
В таких случаях используют динамические хранилища. В Delphi такими хранилищами являются динамические массивы, объект TMemoryStream, динамическое перераспределение памяти. Все эти хранилища работают на одном и том же принципе: под хранение данных выделяется блок памяти и поступающие данные последовательно записываются в этот блок, когда этот блок заполняется полностью, он перераспределяется с некоторым запасом (размер его увеличивается, а старые данные остаются). После того как каждый новый блок заполняется полностью он снова перераспределяется по мере поступления новых данных.
Перераспределение памяти занимает много ресурсов само по себе, а так как оно выполняется еще и в куче, то можно считать его вдвойне неэффективным, особенно если размеры перераспределяемых блоков становятся очень большими. Динамические массивы и динамическое перераспределение памяти используют менеджер кучи Delphi, а объект TMemoryStream использует стандартный менеджер кучи Windows.
Кроме того постоянное перераспределение участков памяти с разными размерами приводит к сильной дефрагментации памяти компьютера, что приводит к замедлению работы компьютера, а в конечном счете и к блокировке его работы.
Для решения проблемы накопления данных автором были разработаны два объекта накопления данных, основанные на двух разных принципах и имеющих разные характеристики.
TLinearStorage
Если размер буфера большой, но максимально возможный размер известен (например если есть ограничение на объем записываемых данных), то можно поступить следующим образом. В адресном пространстве процесса резервируется блок памяти необходимого размера, напомним, что такая операция не занимает ресурсов у системы. Затем по мере необходимости в этом зарезервированном участке памяти, по мере необходимости, последовательно выделяются страницы реальной памяти. Достоинством такого метода является линейное расположение ячеек в памяти друг за другом, то есть к такому хранилищу можно обращаться как к обычному линейному массиву. Недостатком - необходимость указания максимального размера.
TSectionStorage
Если размер буфера заранее неизвестен (ограничен лишь размером доступной реальной памяти), то предыдущее решение не подходит. В этом случае можно предложить другое решение. По мере необходимости, у системы можно запрашивать участки памяти одинакового размера и записывать в них поступающие данные. При этом буфер не будет иметь линейного адресного пространства, а будет состоять из одноразмерных "лоскутов" памяти - для вычислительного алгоритма такая организация буфера пожет стать серьезной помехой. Достоинством же такого решения является отсутствие необходимости изначально указывать какой либо размер буфера.
Если предполагается интенсивное увеличение-уменьшение хранилища, причем желательно, чтобы приращения были небольшими, то можно запрашивать память не у системы, а у стандартного менеджера кучи Windows, который создается для каждого хранилища отдельно. При этом, менеджер кучи выполняет роль кэша страниц памяти, увеличивая производительность.
Дополнительно, каждое хранилище имеет функции записи и чтения в стандартные потоки Delphi с упаковкой. Упаковка производится по стандартным алгоритмам библиотеки ZLIB.
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!