Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Статический массив неизвестной длины / 25 сообщений из 32, страница 1 из 2
24.01.2020, 13:49
    #39918378
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Задача: нужен класс контейнер, который будет хранить до 5-6 элементов. Количество элементов известно на этапе компиляции.

Писать так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
TContainer = class
  FChilds: array of TMyObject;
  constructor Create(ACount: Integer);
end;

constructor TContainer.Create(ACount: Integer);
begin
  SetLength(FChilds, ACount);
end;

не могу из-за жесткого ограничения по памяти (оверхед при выделении памяти для динамического массива, а контейнеров создается очень много). По этой же причине не нравится
Код: pascal
1.
GetMem(FChilds, ACount * SizeOf(TMyObject))



Сейчас делаю так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
TContainer1 = class
  FChild1: TMyObject;
end;

TContainer2 = class(TContainer1)
  FChild2: TMyObject;
end;
........
TContainer5 = class(TContainer4)
  FChild5: TMyObject;
end;

оверхеда нет вообще, но много кода.

Можно как-то подсократить?

Пытался так
Код: pascal
1.
2.
3.
TContainer<T> = class
  FChilds: array[0..SizeOf(T) - 1] of TMyObject;
end;

но компилятор не считает SizeOf(T) константой.

С уважением, Vasilisk
...
Рейтинг: 0 / 0
24.01.2020, 14:13
    #39918384
Sinemurius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Сколько контейнеров и сколько элементов в одном контейнере Вы максимально хотите создать ?
...
Рейтинг: 0 / 0
24.01.2020, 14:46
    #39918398
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_
Задача: нужен класс контейнер, который будет хранить до 5-6 элементов. Количество элементов известно на этапе компиляции.

Писать так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
TContainer = class
  FChilds: array of TMyObject;
  constructor Create(ACount: Integer);
end;

constructor TContainer.Create(ACount: Integer);
begin
  SetLength(FChilds, ACount);
end;

не могу из-за жесткого ограничения по памяти (оверхед при выделении памяти для динамического массива, а контейнеров создается очень много). По этой же причине не нравится
Код: pascal
1.
GetMem(FChilds, ACount * SizeOf(TMyObject))



О каком оверхеде идет речь?
Код: pascal
1.
SetLength(FChilds, 1000);


выделит ~4 Кб памяти
...
Рейтинг: 0 / 0
24.01.2020, 14:50
    #39918400
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_,

Перекрыть NewInstance не рассматривали? Можно выделить чуть больше памяти и хранить там массив, оверхеда быть не должно.
...
Рейтинг: 0 / 0
24.01.2020, 15:01
    #39918405
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
x1ca4064
Перекрыть NewInstance не рассматривали? Можно выделить чуть больше памяти и хранить там массив, оверхеда быть не должно.

А потом, кто-нибудь станет использовать для объекта синхронизацию монитором...
...
Рейтинг: 0 / 0
24.01.2020, 16:45
    #39918455
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Кмк, говорить об оверхеде и при этом применять классы-контейнеры, содержащие классы же - это странно. Но окей, допустим.
В таком случае можно, например, использовать нечто вроде:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
TBaseContainer = class
  property Item read Get write Put
end;

TContainer1 = class(TBaseContainer)
  FObj1
end;

TContainer2 = class(TBaseContainer)
  FObj1, FObj2
end;

...

function CreateContainer(Num: Integer): TBaseContainer;
begin
  case Num of
    1: Result := TContainer1.Create;
   ...
end;

Container := CreateContainer(3);



UPD А еще (для любителей проктостоматологии) размер объекта у класса вычисляется как
Код: pascal
1.
2.
3.
4.
class function TObject.InstanceSize: Longint;
begin
  Result := PInteger(PByte(Self) + vmtInstanceSize)^;
end;


соответственно известно что делать
...
Рейтинг: 0 / 0
24.01.2020, 16:49
    #39918461
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Перейдете с классов на пакед рекорды - сэкономите память.
...
Рейтинг: 0 / 0
24.01.2020, 16:59
    #39918473
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Вообще, если говорить о затратах памяти, любой объект изначально уже тратит больше 100 байт только на х32 (vmtCreateObject - vmtSelfPtr). Это еще не считая оверхеда менеджера памяти и своих виртуальных методов и не говоря про х64. Короче, классы - это не вариант, если нужно экономить память
...
Рейтинг: 0 / 0
24.01.2020, 17:10
    #39918477
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Василий 2
Вообще, если говорить о затратах памяти, любой объект изначально уже тратит больше 100 байт только на х32

Да ты гонишь. Объект минимум - 4 байта - ссылка на VMT класса.
...
Рейтинг: 0 / 0
24.01.2020, 17:23
    #39918491
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Kazantsev Alexey
Объект минимум - 4 байта

Сам себя поправлю, таки 8 байт. В размер включается ссылка на монитор. Соответственно, ничего страшного не случится даже если 22066064 .
...
Рейтинг: 0 / 0
24.01.2020, 17:39
    #39918493
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Sinemurius
Сколько контейнеров
Много. Несколько сотен. Может тысяча
Sinemurius
и сколько элементов в одном контейнере Вы максимально хотите создать ?
Не более 4. Ну может где-то появится с 5
Квейд
О каком оверхеде идет речь?
Код: pascal
1.
SetLength(FChilds, 1000);


выделит ~4 Кб памяти
Код: pascal
1.
SetLength(FChilds, 2)

выделит 8 байт на сам массив + 8 байт на это
Код: pascal
1.
2.
3.
4.
5.
6.
7.
  TDynArrayRec = packed record
  {$IFDEF CPUX64}
    _Padding: LongInt; // Make 16 byte align for payload..
  {$ENDIF}
    RefCnt: LongInt;
    Length: NativeInt;
  end;

итого оверхед 50%
x1ca4064
Перекрыть NewInstance не рассматривали?
Так, мысль интересная. Нужно подумать.

Kazantsev Alexey
А потом, кто-нибудь станет использовать для объекта синхронизацию монитором...
И в чем противопоказания?

Василий 2
В таком случае можно, например, использовать нечто вроде
Вы исходный вопрос читали? Именно от этого варианта и хочется уйти
...
Рейтинг: 0 / 0
24.01.2020, 17:40
    #39918494
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
x1ca4064
Перекрыть NewInstance не рассматривали?
А как туда передать размер?
...
Рейтинг: 0 / 0
24.01.2020, 17:52
    #39918500
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_
И в чем противопоказания?

Да уже ни в чём. InstanceSize возвращает размер с учётом ссылки на монитор.
...
Рейтинг: 0 / 0
24.01.2020, 17:53
    #39918501
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_
Много. Несколько сотен. Может тысяча

Эм... Это из-за 4-8 KB такая заморока???
...
Рейтинг: 0 / 0
24.01.2020, 18:14
    #39918511
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Kazantsev Alexey
Эм... Это из-за 4-8 KB такая заморока???
Нет. Почему-то отжирается памяти на порядок больше, чем общий размер объектов.

Создается тысячи мелких объектов (InstanceSize < 100 байт) и у системы отжирается 100 мегабайт. Создание этих объектов для 10 владельцев и OutOfMemory. Сейчас после базового рефракторинга удалось сократить базовое выделение до 20 мегабайт.

Где-то FastMM чудит и забирает у системы память сильно про запас
...
Рейтинг: 0 / 0
24.01.2020, 18:32
    #39918522
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_
Где-то FastMM чудит и забирает у системы память сильно про запас

Посмотри демку Usage Tracker. Она даёт полную картину выделения памяти, размеры блоков, степень оверхеда.
...
Рейтинг: 0 / 0
24.01.2020, 18:43
    #39918524
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Василий 2
Вообще, если говорить о затратах памяти, любой объект изначально уже тратит больше 100 байт только на х32 (vmtCreateObject - vmtSelfPtr). Это еще не считая оверхеда менеджера памяти и своих виртуальных методов и не говоря про х64. Короче, классы - это не вариант, если нужно экономить память


проверил. Что TObject.Create, что New(pInteger) занимают 16 байт (даже в x64). Видимо, для TObject там только указатель на VMT и резервный указатель на Monitor.
...
Рейтинг: 0 / 0
24.01.2020, 18:59
    #39918533
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Вот Usage Tracker. Можно посмотреть какие реальные размеры блоков использует менеджер. Например, при выделении 13 байт реально выделяется 20 из пула размером 29488. P.S. Данные для XE2, на более поздних они могут отличаться. P.P.S. Проверил в 10.3 - размеры те же.
...
Рейтинг: 0 / 0
24.01.2020, 19:16
    #39918540
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
10.3
...
Рейтинг: 0 / 0
24.01.2020, 19:54
    #39918549
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Kazantsev Alexey
Посмотри демку Usage Tracker.
Где ее брать?
...
Рейтинг: 0 / 0
24.01.2020, 20:14
    #39918551
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_
Где ее брать?

Стандартная демка дельфийская. Правда с какой-то версии её перестали поставлять, но в XE2 она точно есть. Может есть в их репе с демками.
...
Рейтинг: 0 / 0
24.01.2020, 20:23
    #39918553
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Нашёл . XE6 последняя, где эта демка была.
...
Рейтинг: 0 / 0
25.01.2020, 00:08
    #39918585
x1ca4064
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
_Vasilisk_
x1ca4064
Перекрыть NewInstance не рассматривали?
А как туда передать размер?


Я бы делал через
Код: sql
1.
class function InternalArrayLength:integer; virtual;


соответственно для разных TContainer1..5 возвращал кол-во элементов массива, хотя можно и через какой-нибудь threadvar, но это как-то не так
...
Рейтинг: 0 / 0
25.01.2020, 00:16
    #39918587
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
Что мешает сделать статический массив максимального требуемого размера и использовать только нужную его часть?
Накладные расходы - пара лишних байт, тут уж точно никакого перерасхода памяти не будет.
...
Рейтинг: 0 / 0
25.01.2020, 00:58
    #39918600
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Статический массив неизвестной длины
alekcvp,

Зашибись, типа собственный менеджер памяти давай напишем.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Статический массив неизвестной длины / 25 сообщений из 32, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]