Как правильно освобождать память?
Модератор: Модераторы
не в хранилище дело, а то, что при каждой операции с данными - TList проверяет, есть ли подписчики, и видимо блокирует себя, что-то типа TList.Lock/Tlist.Unlock. Все это ухудшает производительность, если подписчиков нет и их использование не предполагается. Лучше брать сразу TFPList, без нотификации.
Дело какраз в хранилище, нотификация тут сбоку-припеку)) TFPList сольет обычному массиву, т.к. сделан он совсем не для хранения таких данных.
Вот здесь вкратце,
про то как её (память) не занимать
там про const, var и out: http://freepascal.ru/article/freepascal/20070520123650/
про то как её (память) не занимать
там про const, var и out: http://freepascal.ru/article/freepascal/20070520123650/
TList - это, по первоначальной задумке, обертка на буфером с указателями, призванная обеспечить:
* Доступ по индексу с проверкой границ и без
* Добавление/удаление, сортировку и т.п.
* Через наследование (до generic-ов) скрыть приведение типов и упростить последующее использование
Динамический массив:
* обеспечить преемственность со статическими массивами (решить проблему с экономией памяти без необходимости резервировать заранее много и т.п.)
* упростить копирование данных между массивами
* решить задачу с проверкой типов и управлением памятью, позволив разработчику сосредоточится на прикладных алгоритмических задачах
По хорошему, реализация динамического массива производится через TList с расширением на подсчет ссылок, хранением размера элементов.
* Доступ по индексу с проверкой границ и без
* Добавление/удаление, сортировку и т.п.
* Через наследование (до generic-ов) скрыть приведение типов и упростить последующее использование
Динамический массив:
* обеспечить преемственность со статическими массивами (решить проблему с экономией памяти без необходимости резервировать заранее много и т.п.)
* упростить копирование данных между массивами
* решить задачу с проверкой типов и управлением памятью, позволив разработчику сосредоточится на прикладных алгоритмических задачах
По хорошему, реализация динамического массива производится через TList с расширением на подсчет ссылок, хранением размера элементов.
>>TList - это, по первоначальной задумке, обертка на буфером с указателями, призванная обеспечить:
Позволю себе пофиксить: это обертка над массивом указателей
Т.е. по сути тотже массив с некоторыми плюшками, но существенным ограничением - элементы являются указателями. Прекрасно подходит для хранения ссылок на какиелибо крупные данные и совершенно не годится для хранения мелочи - память надо выделять как под сам массив, так и под каждый элемент данных.
В случае топикстартера использование TList влечет за собой оверхед в виде 33% перерасхода памяти (считаю что sizeof(pointer)=sizeof(real)), и тотальную просадку производительности при добавлении точек в массив связаную с отдельным выделением памяти под каждую точку.
>>По хорошему, реализация динамического массива производится через TList с расширением на подсчет ссылок, хранением размера элементов.
По хорошему надо TFPGList или TVector из fcl-stl. А чтоб таких вопросов не возникало в дальнейшем можно сделать свою обертку над динамическим\статическим массивом... для прояснения, а потом вернуться на стандартные решения))
Позволю себе пофиксить: это обертка над массивом указателей
Т.е. по сути тотже массив с некоторыми плюшками, но существенным ограничением - элементы являются указателями. Прекрасно подходит для хранения ссылок на какиелибо крупные данные и совершенно не годится для хранения мелочи - память надо выделять как под сам массив, так и под каждый элемент данных.
В случае топикстартера использование TList влечет за собой оверхед в виде 33% перерасхода памяти (считаю что sizeof(pointer)=sizeof(real)), и тотальную просадку производительности при добавлении точек в массив связаную с отдельным выделением памяти под каждую точку.
>>По хорошему, реализация динамического массива производится через TList с расширением на подсчет ссылок, хранением размера элементов.
По хорошему надо TFPGList или TVector из fcl-stl. А чтоб таких вопросов не возникало в дальнейшем можно сделать свою обертку над динамическим\статическим массивом... для прояснения, а потом вернуться на стандартные решения))
в каждом из этих вызовов пришлось бы делать setLength(), которая будет перевыделять память/копировать из старого массива(блока памяти) в новый
Менеджер памяти всегда округляет в бОльшую сторону, выделяя кусок памяти с запасом (как конкретно - эзотерика еси). Поэтому добавление по одному элементу - это плохо, но не смертельно. Большинство вызовов SetLength() сведётся к "Ага, пока влезает, меняем только поле размера массива" - т.е. практически к стоимости самого вызова.
Та же история со строками.
На массивах/строках в десятки элементов, добавление по одному можно считать условно-бесплатным.
З.Ы. На деле, SetLength() вызывает какую-то встроенную процедуру Паскаля для задания размера массива (забыл имя), а уже та - менеджер памяти.
