Динамический массив любого типа

Общие вопросы программирования, алгоритмы и т.п.

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

Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

вот и получается - сколькото довыделений и сколькото полноценных выделений с перемещением

А как насчет StrNew(Pchar) vs AnsiString(refcounting) ?
Mirage
энтузиаст
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

По поводу исходной проблемы:
Есть класс-враппер для динамического массива любого типа.
http://blog.synopse.info/post/2011/03/1 ... -fast-RTTI
Умеет в том числе и размер менять.
Можно посмотреть как там реализована setCapacity().
А можно и использовать готовое, чем черт не шутит.

Вообще надо уже как-то прекращать этот велосипедный беспредел. Например, создать что-то вроде apache foundation. Еще необходим стандарт на подтягивание зависимостей.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

debi12345
>>А как насчет StrNew(Pchar) vs AnsiString(refcounting)?
много в вашем массиве будет одинаковых строк? Думаю их вообще небудет - если откуданибудь извне прочитать 300К одинаковых строк - они всеравно будут "разными" а не одной строкой с refcount=300К. в данной примере разницы ИМХО вообще не будет - стринги всеравно создаются из пчаров копированием, а потом уничтожается

Добавлено спустя 1 минуту 21 секунду:
Mirage
>>Вообще надо уже как-то прекращать этот велосипедный беспредел.
fpc-stl чем не велокиллер? тем что на генериках?
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

fpc-stl чем не велокиллер?

А на нем можно сделать данную задачу ?
Mirage
энтузиаст
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

zub писал(а):fpc-stl чем не велокиллер? тем что на генериках?

Совместим с Delphi?
Я, например, о нем первый раз слышу, да и подозреваю он только о контейнерах.
С трудом нагуглил что-то об этой либе - ПДФку.
Сразу:
TSet is an ordered container of unique elements
THashSet is an unordered container of unique elements
Т.е. просто TSet у них это то, что должно называться TTreeSet.
Короче, именование неконсистентно.
Кстати, библиотек с контейнерами полно на любой вкус. Стандарта нет. Т.е. той, которую будут использовать с наибольшей вероятностью. Мне, например непонятно, зачем использовать fpc-stl.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

debi12345
>>на нем можно сделать данную задачу ?
а почему нет, это просто обертка над динмассивом с допфичами

Mirage
С делфи не совместим.
Использовать пакет идущий в составе fpc думаю надежней чем чтото сторонее
>>Короче, именование неконсистентно.
хз, незнаком с такими тонкостями
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

это просто обертка над динмассивом с допфичами

Но элементы-тов нашей задаче разнородые - то есть опять придется использовать TObject как элемент массива - то есть темплэйтовость (настройка на тип) аннулируется. В чем тогда преимущево над Вашим вариантом "1" ? Позволит обойтись без SetLength ?
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Но элементы-тов нашей задаче разнородые
в смысле разнородные - однородные - с одинаковым sizeof и индексным доступом.

zamtmn@zamtmn-desktop:/mnt/wind/array$ time ./v4
Heap dump by heaptrc unit
1800025 memory blocks allocated : 124043278/129349960
1800025 memory blocks freed : 124043278/129349960
0 unfreed memory blocks : 0
True heap size : 57376768
True free heap : 57376768

real 0m1.256s
user 0m1.224s
sys 0m0.028s

zamtmn@zamtmn-desktop:/mnt/wind/array$ time ./v4

real 0m0.235s
user 0m0.208s
sys 0m0.024s

вариант с fpc-stl скоростью не блестанул, причем что добавлять элементы по одному, что выделить под них память сразу - отличается несильно. первый запуск был с -gh, второй соответственно без него
Mirage
энтузиаст
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

Т.е. оно еще и тормоз? Куда уж тут до велокиллера...
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

Тоже довольно быстрый код - на базе DCALC (юниты приатачены) :

Код: Выделить всё

program test;

{$mode objfpc}{$h+}

uses
  decal          in 'decal\decal.pas',
  mwfixedrecsort in 'decal\mwfixedrecsort.pas',
  sysutils,
  classes
;
const
  TEST_CNT = 300000;

type

  chmoclass = class
   public
    int_val: integer;
    str_val: widestring;
    constructor create(const aint: integer; const astr: widestring);
  end;

  constructor chmoclass.create(const aint: integer; const astr: widestring);
  begin
    int_val:= aint;
    str_val:= astr;
  end;

  procedure PrintData(ptr: pointer; const obj: dobject);
  begin
  case obj.vtype of
    vtInteger:   
      writeln('atomic int = ',asInteger(obj));
    vtString,vtWidestring:
      writeln('atomic widestring = ',asWideString(obj));
    vtExtended:
      writeln('atomic real = ',asEXtended(obj));
    vtObject: begin
      with chmoclass(asClass(obj)) do begin
        writeln('chmo data = {',int_val,',',str_val,'}');
        free;
      end;
    end;
  end;
  end;

var
  lst1: dlist;
  i: integer;

begin

  lst1:= dlist.create;
  for i:= 0 to TEST_CNT do begin
    lst1.add([i]);
    lst1.add([extended(i)]);
    lst1.add([widestring(inttostr(i) + ' as text')]);
    lst1.add([chmoclass.create(i,inttostr(i) +' as text in CHMOREC')]);
  end;

  foreach(lst1,MakeApply({$ifdef fpc}@{$endif}PrintData));
  lst1.free;

end.


Особенности:
1) использует связанный список вместо массива - это позволяет отказаться от SETLENGTH
2) можно работать с родными рефкаунтед-строками вместа ненативного динпамятного PCHAR
Конструктор класса (реально без указания предка = TOBJECT ) в принципе можно вынести в INLINE.

Напишите сколько у Вас получается.
Вложения
decal.rar
(50.67 КБ) 509 скачиваний
Последний раз редактировалось debi12345 23.07.2013 02:32:26, всего редактировалось 1 раз.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

вариант с decal`ом. вывод массива закоментирован
zamtmn@zamtmn-desktop:/mnt/wind/array/v5$ time ./v5

real 0m0.360s
user 0m0.316s
sys 0m0.040s


>>Т.е. оно еще и тормоз? Куда уж тут до велокиллера...
не тормоз. выше я озвучил результаты для вариантов без setlength - массив был выделен за 1 раз. а в тесте с фпцстлным tvector идет добавление в массив по одному элементу
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

На моей машине в 3 раза обгоняет мой (1-й) вариант - котрый с поэлементным SETLEGHTH. Резервирование памяти с запасом для более редкой реаллокации в случае списка не нужно в принципе.
Можно потестирвать и другие типы STL - и DCALC-контейнеров :)
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Ваш эталонный вариант с вариантным рекордом и поэлементным добавлением у меня выдал
zamtmn@zamtmn-desktop:/mnt/wind/array$ time ./v0

real 0m1.485s
user 0m0.776s
sys 0m0.704s
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

Еще раз протестировал варианты с поэлементным (как это будет в реальной жизни) перераспределением :

1) копирование в VARIANT - не дождался завершения (!)
2) UNION-based : 4 сек
3) TOBJECT-based, минимальный размер элементов : 2 сек
4) TOBJECT-based, размер элементов с запасом: 5 сек
5) DCALC.DLIST : 1.5 сек
6) DCALC.DARRAY : 2 сек

Хм.. Пока что склоняюсь к вариантам на DCALC, плюс в них можно работать со строками, а не указателями на строки.
У Вас есть полный код примера на FPC-STL (2.6.2) ?
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>У Вас есть полный код примера на FPC-STL (2.6.2) ?

Код: Выделить всё

program v4;
{$mode objfpc}{$h+}

uses
  sysutils,strings,gvector;

const
  TEST_CNT = 300000;

type

  chmorec = packed record
    int_val: integer;
    str_val: pchar;
  end;
  pchmorec = ^chmorec;

  ANYTYPE = (INT_T,TEXT_T,REAL_T,CHMO_T);

  anydatarecty = packed record
    case data_type:ANYTYPE of
      INT_T:  (ival: integer);
      TEXT_T: (tval: pchar);
      REAL_T: (rval: double);
      CHMO_T: (chmoval: chmorec);
  end;
  //anydatarecarty = array of anydatarecty;
  anydatarecarty=specialize TVector<anydatarecty>;


procedure addelem(var arr: anydatarecarty; atype:ANYTYPE; adataptr: pointer);
var
   adata:anydatarecty;
begin
  //setlength(arr,length(arr)+1);
  adata.data_type:= atype;

//  case integer(atype) of
//    integer(INT_T): arr[high(arr)].ival:= integer(adataptr^);
//    integer(TEXT_T): arr[high(arr)].tval:= strnew(pchar(adataptr));
//    integer(REAL_T): arr[high(arr)].rval:= double(adataptr^);
//    integer(CHMO_T): begin
//      with arr[high(arr)].chmoval do begin
//        int_val:= (chmorec(adataptr^)).int_val;
//        str_val:= strnew((chmorec(adataptr^)).str_val);
//      end;
//    end;
//  end;


  case atype of
    INT_T: adata.ival:= integer(adataptr^);
    TEXT_T: adata.tval:= strnew(pchar(adataptr));
    REAL_T: adata.rval:= double(adataptr^);
    CHMO_T: begin
      with adata.chmoval do begin
        int_val:= (chmorec(adataptr^)).int_val;
        str_val:= strnew((chmorec(adataptr^)).str_val);
      end;
    end;
  end;
  arr.PushBack(adata);


end;


var
 arr1: anydatarecarty;
 i1: integer;
 pch1: pchar;
 r1: double;
 chmo1: chmorec;
 i: integer;

begin
  arr1:=anydatarecarty.Create;
  for i:= 0 to TEST_CNT do begin
    i1:= i;
    addelem(arr1,INT_T,@i1);

    r1:= double(i);
    addelem(arr1,REAL_T,@r1);

    pch1:= pchar(inttostr(i) + ' as text');
    addelem(arr1,TEXT_T,pch1);

    chmo1.int_val:= i;
    chmo1.str_val:= pchar(inttostr(i) +' as text in CHMOREC');
    addelem(arr1,CHMO_T,@chmo1);
  end;


  for i:=arr1.Size downto 0 do begin
    case integer(arr1[i].data_type) of
//    integer(INT_T):  writeln('int val = ',  arr1[i].ival);
      integer(TEXT_T): begin
//        writeln('text val = ', arr1[i].tval);
        dispose(arr1[i].tval);
      end;
//      integer(REAL_T): writeln('real val = ', arr1[i].rval);
      integer(CHMO_T): begin
//        writeln('chmo rec = {', arr1[i].chmoval.int_val,',',arr1[i].chmoval.str_val, '}');
        dispose(arr1[i].chmoval.str_val);
      end;
    end;
  end;
  arr1.Destroy;

end.

В зависимости проекта подключить FCL
На 2.6.x скорее всего придется самостоятельно скомпилировать fpc-stl, когда я пробовал эти версии он не компилировался при установке
Ответить