Аналог TStringList для записей

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Re: Аналог TStringList для записей

Сообщение VirtUX » 16.02.2014 18:05:11

svk12 писал(а):И вставляйте его в TStringList.

VirtUX писал(а):Создавать целые объекты для миллионов параметров AnyParam мне кажется ресурсозатратным для ОЗУ.

Вот сколько будет выделено памяти под TPointerStore? Я так понимаю, что память будет занята всеми его полями, которые мне не нужны. И ОЗУ будет хранить более 50% всякого не нужного мусора. Или я не правильно понимаю выделение памяти под новый экземпляр TObject?

Добавлено спустя 20 минут 11 секунд:
Например: имеем 1 миллиард параметров. каждый параметр имеет идентификатор длиной в 10 байт (например: 'а000000001'). Параметр занимает в памяти 12 байт
Код: Выделить всё
ParamForExample = record
pos: int64;
offset: DWord;
end;

Если использовать Pointer, то под каждый параметр будет использовано 12 + 4 (32bit) или 12 + 8 (64bit) байт в ОЗУ. А сколько будет использовано под класс, включающий в себя эти 16 или 20 байт? И умножим это на 1 миллиард. Сколько будет не нужного мусора в ОЗУ? Сколько занимает памяти сам TObject?
32 Гб ОЗУ под параметры мне сейчас не проблема выделить. Но если больше, то придется свопироваться, или разбивать на страницы. Но тогда теряем производительность.
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Аналог TStringList для записей

Сообщение svk12 » 16.02.2014 19:15:25

VirtUX писал(а):Сколько занимает памяти сам TObject?


Адрес VMT - 4 или 8 байт (32/64).
svk12
постоялец
 
Сообщения: 409
Зарегистрирован: 09.06.2008 18:42:47

Re: Аналог TStringList для записей

Сообщение VirtUX » 16.02.2014 20:02:12

Эксперимент проводится на openSuSE 13.1 32bit, Lazarus 1.0.14, FPC 2.6.2
===========
Странный эффект (наблюдаю в списке процессов KDE 4.11.5):
Типы:
Код: Выделить всё
type
re = record
i: int64;
d: dword;
end;
pre = ^re;
tre = class
  f: re;
end;

Если запустить так:
Код: Выделить всё
var
a: array [1 .. $FFFFFF] of TObject;
...
var
  i: DWord;
begin
  for i := 1 to $FFFFFF do a[i] := TObject.Create;

то занимаемая память ~334 Mb
если так:
Код: Выделить всё
var
a: array [1 .. $FFFFFF] of tre;
...
var
  i: DWord;
begin
  for i := 1 to $FFFFFF do a[i] := tre.Create;

то занимаемая память ~597 Mb, что логично. Т.к. добавились ~268 Mb данных (re)
Теперь так:
Код: Выделить всё
var
a: array [1 .. $FFFFFF] of re;
...
var
  i: DWord;
begin
  for i := 1 to $FFFFFF do a[i].d :=i ;

и занимаемая память ~ 268 Mb - все отлично, как и должно быть. Но теперь:
Код: Выделить всё
var
a: array [1 .. $FFFFFF] of pre;
...
var
  i: DWord;
begin
  for i := 1 to $FFFFFF do new(a[i]);

и память снова ~597 Mb!!! С чего это?.. Дополнительно ~19 байт на каждую запись.
Если так:
Код: Выделить всё
type
re = record
i: int64;
d: dword;
end;
pre = ^re;
tre = class
  f: pre;
end;
...
var
a: array [1 .. $FFFFFF] of tre;
...
var
  i: DWord;
begin
  for i := 1 to $FFFFFF do begin
  a[i] := tre.Create;
  new(a[i].f);

то все ~859 Mb.

Где-то я читал, что чистый TObject занимает ~20 байт. Получается: хоть Pointer используй, хоть TObject - все одно к каждой записи + 20 байт. Я правильно понимаю?
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Аналог TStringList для записей

Сообщение zub » 17.02.2014 00:34:58

VirtUX
>>Где бы взять такой TStringList, имеющий возможность хранить просто Pointer вместо TObject? Или как обмануть TStringList?
Кто мешает подсунуть Pointer вместо TObject в обычный TStringList? переменная TObject по сути это обычный указатель

>>Сколько занимает памяти сам TObject?
посмотрите что вернет TObject.InstanceSize. насколько помню должно быть sizeof(pointer) - указатель на описание класса - структуру данных TVMT.
т.е.
Код: Выделить всё
var
  MyClass:tobject;
...
  MyClass:=TObject.Create
...

в результате в MyClass будет указатель на sizeof(pointer) байт в куче, а в этих байтах будет указатель на TVMT TObject`а

Массив классов грубо говоря это массив указателей и если вы собираетесь хранить миллиард "чегото там" - классы плохое решение, особенно если "чегото там" это небольшие данные:
-доступ через указатели=хранение ненужных указателей при индексном доступе
-накладные расходы "лишнего" TObject.InstanceSize
-невозможность выделить память под всё сразу=отдельное выделение под каждый экземпляр
Для мелочи имхо лучше использовать обьекты или рекорды

>>Есть массив параметров типа record. Есть список строковых идентификаторов для этого массива параметров. Сейчас это выглядит в двух вариантах:
Поглядите gmap из fpc-stl телепатор подсказывает что это именно то что вам надо
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Аналог TStringList для записей

Сообщение VirtUX » 17.02.2014 14:11:17

gmap из fcl-stl не имеет встроенной сортировки и прочих вкусностей TStringList.
zub писал(а):Кто мешает подсунуть Pointer вместо TObject в обычный TStringList?

Мистика :) Вчера вываливалось с ошибкой. Сегодня переустановил Лазаря. Ничего не менял в конфах, проектах. Ну... совсем ничего не менял, и... сегодня проглотило :)
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
type
  ro = record
    i: int64;
    d: DWord;
  end;
  pro = ^ro;

var
  sl: TStringList;
  i: DWord;
begin

  sl := TStringList.Create;

    for i := 0 to $FFFFFF
    do begin
      sl.AddObject('', TObject(GetMem(SizeOf(ro))));
      pro(sl.Objects[i])^.d:= i;
      pro(sl.Objects[i])^.i:= i;
    end;

  // Деструкция в другой процедуре

end;

Мой вопрос закрыт
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Пред.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 230

Рейтинг@Mail.ru