powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Список классов vs списка записей - в чем преимущество?
63 сообщений из 63, показаны все 3 страниц
Список классов vs списка записей - в чем преимущество?
    #39762359
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Наткнулся на один интересный коммент Peter Below'a - https://en.delphipraxis.net/topic/576-maintaining-for-loops/?tab=comments#comment-4225
Instead of
Код: pascal
1.
Projects: TArray<TProject>


use a list class:
Код: pascal
1.
2.
3.
4.
type
  TProjectList = class(TList<TProject>)
    
  end;  


Add public methods to the class that implement your current for loops. This way you have all this code centralized in one place, which should massively simplify the maintenance. And while you're at it: convert the record into a class. Lists of records are a bit inefficient since accessing the items in the list involves a lot of copying of data. You can then use a TObjectlist<TProject> as base class for your TProjectlist and let the list manage the memory of the TProject objects you add to it (OwnsObjects parameter for the list constructor set to true, which is the default).
Может кто "разжевать" выделенное жирным?
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762365
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingМожет кто "разжевать" выделенное жирным?

TObject это указатель. record это POD тип.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762372
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYing,

очередная агитация за конвертить записи в классы, хотя казалось что идиоты кончились уже
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762378
LiYing
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kealon(Ruslan)очередная агитация за конвертить записи в классы, хотя казалось что идиоты кончились уже
Да вроде как неудобно называть человека из команды TeamB идиотом :)
Так стоит все же следовать его совету или нет?
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762379
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingТак стоит все же следовать его совету или нет?

Стоит мозгом подумать об отличии array of record от array of TObject.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762386
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingkealon(Ruslan)очередная агитация за конвертить записи в классы, хотя казалось что идиоты кончились уже
Да вроде как неудобно называть человека из команды TeamB идиотом :)
Так стоит все же следовать его совету или нет?не стоит
чудные люди, наплодят дырявых абстракций, а потом советы раздают как с этим жить
сделай простую обёртку с получением адреса и все проблемы с производительностью исчезнут
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762387
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
- Дверь? Котора дверь?
- Котора дверь! Вот эта.
- Эта? Прилагательна.
- Почему ж?
- Потому что она приложена к своему месту.

всё хорошо в меру и к месту.
но есть ещё и МОДНЫЕ веяния...
а Петя Бигелоу, тот ещё "евангелист".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762389
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYingТак стоит все же следовать его совету или нет?Зависит от... Часто стоит в том числе и из-за перформанса.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762391
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)чудные люди, наплодят дырявых абстракций, а потом советы раздают как с этим жить
сделай простую обёртку с получением адреса и все проблемы с производительностью исчезнутНу конечно лучше плодить костыли
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762392
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYing,

Всё верно он говорит.

1. Что ты там будешь делать с TArray не понятно и не наглядно.
2. У массива нет методов
3. В результате - ты ничего не выигрываешь, кроме выноса мозга.
4. TList/TObjectList/TDictionary/TObjectDictionary - стандартные классы для работы со списками. Причём не только для Delphi. Не делай своих велосипедов.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762393
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
21.01.2019 14:42, white_nigger пишет:
> Ну конечно лучше плодить костыли

не костыли, а аддоны!


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762402
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_niggerНу конечно лучше плодить костылизачем костыли,
обычный перевод STL, всё апробовано и работает
нормальные итераторы, нормальные контейнеры без заскоков и выделения памяти на каждый чих

куда деваться если стандартная либа вся в ляпах и недоделках
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762413
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)LiYingпропущено...

Да вроде как неудобно называть человека из команды TeamB идиотом :)
Так стоит все же следовать его совету или нет?не стоит
чудные люди, наплодят дырявых абстракций, а потом советы раздают как с этим жить
сделай простую обёртку с получением адреса и все проблемы с производительностью исчезнут Все тут прям замучены нарзаном вопросом о производительности.
А количество тактов процессора ты уже посчитал, которые выиграет TArray<> против TList<>?
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762429
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimonka,

к производительности взывают создатели сего творения, что вызвало у LiYing вполне здравый вопрос
я просто говорю, что не вижу никакого смысла спорить кто быстрее черепаха или улитка
кому надо делают нормальные либы и не парятся
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762543
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ради быстродействия в своем TArrayEx<T> = record даже SetLength захакал. :)


Типа так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
procedure TArrayEx<T>.SetLengthFast(NewValue: integer);
const
  GrowLimit = 64;
begin
  if NewValue<=0 then begin
    FCapacity:=0;
    SetLength(Items,0);
  end else begin
    if (NewValue>FCapacity) or (NewValue shl 1<FCapacity) then begin
      FCapacity:=Min(NewValue shl 1,NewValue+GrowLimit);
      SetLength(Items,FCapacity);
      FArrayCount:=PNativeInt(NativeInt(@Items[0])-SizeOf(NativeInt));
    end;
    FArrayCount^:=NewValue;
  end;
end;
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762552
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Теоретик... Блин.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762556
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimonkaА количество тактов процессора ты уже посчитал, которые выиграет TArray<> против TList<>?
Дело не [только] в тактах, а в многократном выделении/освобождении кучи мелких кусочков памяти вместо одного большого.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762560
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LiYing,

надо не разжовывать выделенное, а смотреть, что дальше написано -- это самое главное. Генерики наше всё. На порядок ускоряет разработку и снижают рутину. Долой бесконечную копипасту с самописными списками и рекордами. А уж про отладку -- так это манна небесная. Все на броневичок генериков!
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762568
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JaDi,

одно другому не мешает
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762569
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gatorkealon(Ruslan),

Теоретик... Блин.хотелось бы, но ещё и код выдавать нужно
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762593
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatРади быстродействия в своем TArrayEx<T> = record даже SetLength захакал. :)


Типа так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
procedure TArrayEx<T>.SetLengthFast(NewValue: integer);
const
  GrowLimit = 64;
begin
  if NewValue<=0 then begin
    FCapacity:=0;
    SetLength(Items,0);
  end else begin
    if (NewValue>FCapacity) or (NewValue shl 1<FCapacity) then begin
      FCapacity:=Min(NewValue shl 1,NewValue+GrowLimit);
      SetLength(Items,FCapacity);
      FArrayCount:=PNativeInt(NativeInt(@Items[0])-SizeOf(NativeInt));
    end;
    FArrayCount^:=NewValue;
  end;
end;



Чистым бредом попахивает, ей богу!

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
type
  ArrayEx<T> = record
    v: array of T;
    CurrentLength: NativeUInt;
    function add(Value: T): NativeUInt;
  end;

function ArrayEx<T>.add(Value: T): NativeUInt;
const
  Plus = 16; // 32
var
  MaxLength: Integer;
begin
  MaxLength := Length(v);
  if CurrentLength >= MaxLength then
    SetLength(v, MaxLength + Plus);

  v[CurrentLength] := Value;
  inc(CurrentLength);
end;



Что может быть легче ??? Ну если это медленно, из за использования length то давайте развратимся

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  ArrayEx<T> = record
    v: array of T;
    CurrentLength: NativeUInt;
    function add(Value: T): NativeUInt;
  end;

function ArrayEx<T>.add(Value: T): NativeUInt;
const
  Plus = 16; // 32
var
  MaxLength: Integer;
begin
  if PDynArrayRec(v) = nil then
    MaxLength := 0
  else
    MaxLength := PDynArrayRec(NativeUInt(v) - SizeOf(TDynArrayRec)).Length;

  if CurrentLength >= MaxLength then
    SetLength(v, MaxLength + Plus);
  v[CurrentLength] := Value;
  inc(CurrentLength);
end;




Не уверен что при оптимизации это что то даст!

Но давайте заменим SetLength на реаллок!!!


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  PDynArrayTypeInfo = ^TDynArrayTypeInfo;

  TDynArrayTypeInfo = packed record
    kind: TTypeKind;
    name: Byte; { string[0]; }
    elSize: Integer;
    elType: ^PDynArrayTypeInfo;
    varType: Integer;
  end;

  ArrayEx<T> = record
    v: TArray<T>;
    CurrentLength: NativeUInt;
    function add(Value: T): NativeUInt;
  end;

procedure ArrayOfPointerSetLength(ptr: PPointer; const NewLength: NativeInt);
  procedure ArrayOfPointerClear(const ptr: PPointer);
    function __DynArrayRefCnt(const A: Pointer): Integer; inline;
    begin
      Result := PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.RefCnt;
    end;

  var
    p: Pointer;
  begin
    p := ptr^;
    if p <> nil then
    begin
      ptr^ := nil;
      if __DynArrayRefCnt(p) > 0 then
      begin
        if AtomicDecrement(PDynArrayRec(PByte(p) - SizeOf(TDynArrayRec))
          ^.RefCnt) = 0 then
        begin
          Dec(PByte(p), SizeOf(TDynArrayRec));
          SysFreeMem(p);
        end;
      end;
    end;
  end;

const
  elSize = SizeOf(Pointer);
var
  oldLength, minLength: NativeInt;
  neededSize: NativeInt;
  p: Pointer;
begin
  p := ptr^;
  neededSize := NewLength * elSize + SizeOf(TDynArrayRec);
  if p = nil then
    p := SysAllocMem(neededSize)
  else
  begin
    Dec(PByte(p), SizeOf(TDynArrayRec));
    oldLength := PDynArrayRec(p).Length;

    if PDynArrayRec(p).RefCnt = 1 then
      p := SysReallocMem(p, neededSize)
    else
    begin
      p := SysGetMem(neededSize);
      minLength := oldLength;
      if minLength > NewLength then
        minLength := NewLength;
      Move(PByte(ptr^)^, (PByte(p) + SizeOf(TDynArrayRec))^,
        minLength * elSize);
      ArrayOfPointerClear(ptr^);
    end;
    if NewLength > oldLength then
      FillChar((PByte(p) + SizeOf(TDynArrayRec) + elSize * oldLength)^,
        elSize * (NewLength - oldLength), 0);
  end;

  PDynArrayRec(p).RefCnt := 1;
  PDynArrayRec(p).Length := NewLength;
  Inc(PByte(p), SizeOf(TDynArrayRec));

  ptr^ := p;
end;

function ArrayEx<T>.add(Value: T): NativeUInt;
const
  Plus = 16; // 32
var
  MaxLength, NewLength: Integer;
  typeInfo, pv: Pointer;
  pv2: PPointer;
begin
  if PDynArrayRec(v) = nil then
    MaxLength := 0
  else
    MaxLength := PDynArrayRec(NativeUInt(v) - SizeOf(TDynArrayRec)).Length;

  if CurrentLength >= MaxLength then
    ArrayOfPointerSetLength(Pointer(@v), MaxLength + Plus);

  v[CurrentLength] := Value;
  Inc(CurrentLength);
end;



Мне кажется,теперь эта по настоящему FAST
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762594
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что может быть легче ??? Ну если это медленно, из за использования length то давайте развратимся

Вариант 1:

Угу. Тупой вариант. Но при нем теряется целостность состава массива v. В конце будет мусор из неиспольземых элементов, что для меня неприемлемо.

Вариант 2:
Тоже самое, только через лоу-левел жопу.


В моем-же варианте я имею и возможность безопасной прямой работы с элементами массива, при этом сохраняя скорость add.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762595
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иными словами мой вариант при высокой скорости добавления элементов в массив сохраняет работоспособность функций Length(Array) и High(Array).
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762601
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Кхм. Странное преимущество. Когда я могу просто MyArray.CurrentLength и получить текущий размер.

rgreat В конце будет мусор из неиспольземых элементов, что для меня неприемлемо.

А ты хранишь типа, ключи к другому массиву ??? Если в другом массиве удалилось значение, то в другом это отобразится и следующий добавленный элемент встанет на место удалённого?


0.722683 секунд, при добавление 50000000 элементов

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  PDynArrayTypeInfo = ^TDynArrayTypeInfo;

  TDynArrayTypeInfo = packed record
    kind: TTypeKind;
    name: Byte; { string[0]; }
    elSize: Integer;
    elType: ^PDynArrayTypeInfo;
    varType: Integer;
  end;

  ArrayEx<T> = record
    v: TArray<T>;
    CurrentLength: NativeUInt;
    function add(Value: T): NativeUInt;
  end;

procedure ArrayOfPointerSetLength(ptr: PPointer; const NewLength: NativeInt);
  procedure ArrayOfPointerClear(const ptr: PPointer);
    function __DynArrayRefCnt(const A: Pointer): Integer; inline;
    begin
      Result := PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.RefCnt;
    end;

  var
    p: Pointer;
  begin
    p := ptr^;
    if p <> nil then
    begin
      ptr^ := nil;
      if __DynArrayRefCnt(p) > 0 then
      begin
        if AtomicDecrement(PDynArrayRec(PByte(p) - SizeOf(TDynArrayRec))
          ^.RefCnt) = 0 then
        begin
          Dec(PByte(p), SizeOf(TDynArrayRec));
          SysFreeMem(p);
        end;
      end;
    end;
  end;

const
  elSize = SizeOf(Pointer);
var
  oldLength, minLength: NativeInt;
  neededSize: NativeInt;
  p: Pointer;
begin
  p := ptr^;
  neededSize := NewLength * elSize + SizeOf(TDynArrayRec);
  if p = nil then
    p := SysAllocMem(neededSize)
  else
  begin
    Dec(PByte(p), SizeOf(TDynArrayRec));
    oldLength := PDynArrayRec(p).Length;

    if PDynArrayRec(p).RefCnt = 1 then
      p := SysReallocMem(p, neededSize)
    else
    begin
      p := SysGetMem(neededSize);
      minLength := oldLength;
      if minLength > NewLength then
        minLength := NewLength;
      Move(PByte(ptr^)^, (PByte(p) + SizeOf(TDynArrayRec))^,
        minLength * elSize);
      ArrayOfPointerClear(ptr^);
    end;
    if NewLength > oldLength then
      FillChar((PByte(p) + SizeOf(TDynArrayRec) + elSize * oldLength)^,
        elSize * (NewLength - oldLength), 0);
  end;

  PDynArrayRec(p).RefCnt := 1;
  PDynArrayRec(p).Length := NewLength;
  Inc(PByte(p), SizeOf(TDynArrayRec));

  ptr^ := p;
end;

function ArrayEx<T>.add(Value: T): NativeUInt;
const
  Plus = 16; // 32
var
  MaxLength, NewLength: Integer;
  typeInfo, pv: Pointer;
  pv2: PPointer;
begin
  if PDynArrayRec(v) = nil then
    MaxLength := 0
  else
    MaxLength := PDynArrayRec(NativeUInt(v) - SizeOf(TDynArrayRec)).Length;

  if CurrentLength >= MaxLength then
    ArrayOfPointerSetLength(Pointer(@v), MaxLength + Plus);

  v[CurrentLength] := Value;
  Inc(CurrentLength);
end;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

var
  arr: ArrayEx<Integer>;
  i: Integer;
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);

    for i := 0 to 50000000 do
      arr.add(i);

    Writeln(PrintTime(T));

    for i := 0 to 50000000 do
      if arr.v[i] <> i then
        Writeln('Faild!!: ' + i.ToString);

    Writeln('End');

    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




Самый простой 0.9 секунд
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  ArrayEx<T> = record
    v: array of T;
    CurrentLength: NativeUInt;
    function add(Value: T): NativeUInt;
  end;

function ArrayEx<T>.add(Value: T): NativeUInt;
const
  Plus = 16; // 32
var
  MaxLength: Integer;
begin
  MaxLength := Length(v);
  if CurrentLength >= MaxLength then
    SetLength(v, MaxLength + Plus);

  v[CurrentLength] := Value;
  inc(CurrentLength);
end;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

var
  arr: ArrayEx<Integer>;
  i: Integer;
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);

    for i := 0 to 50000000 do
      arr.add(i);

    Writeln(PrintTime(T));

    for i := 0 to 50000000 do
      if arr.v[i] <> i then
        Writeln('Faild!!: ' + i.ToString);

    Writeln('End');

    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




На этот Я вообще НЕ надеялся. Но если убрать length то 0.9 сек

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  ArrayEx<T> = record
    v: array of T;
    CurrentLength: NativeUInt;
    function add(Value: T): NativeUInt;
  end;

function ArrayEx<T>.add(Value: T): NativeUInt;
const
  Plus = 16; // 32
var
  MaxLength: Integer;
begin
  if PDynArrayRec(v) = nil then
    MaxLength := 0
  else
    MaxLength := PDynArrayRec(NativeUInt(v) - SizeOf(TDynArrayRec)).Length;

  if CurrentLength >= MaxLength then
    SetLength(v, MaxLength + Plus);
  v[CurrentLength] := Value;
  inc(CurrentLength);
end;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

var
  arr: ArrayEx<Integer>;
  i: Integer;
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);

    for i := 0 to 50000000 do
      arr.add(i);

    Writeln(PrintTime(T));

    for i := 0 to 50000000 do
      if arr.v[i] <> i then
        Writeln('Faild!!: ' + i.ToString);

    Writeln('End');

    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




А теперь обычный TList

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils, classes;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

var
  arr: TList;
  i: Integer;
  T: Int64;

begin
  try
    arr := TList.Create;
    QueryPerformanceCounter(T);

    for i := 0 to 50000000 do
      arr.add(Pointer(i));

    Writeln(PrintTime(T));

    Writeln('End');

    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



Выдал 0.724371

Короче выдумывать костыли не стоит


... Я теперь уверен что и твоя чуда магическая штука, не чуть НЕ быстрее
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762602
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Смог выжить чуточку быстрее

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  PDynArrayTypeInfo = ^TDynArrayTypeInfo;

  TDynArrayTypeInfo = packed record
    kind: TTypeKind;
    name: Byte; { string[0]; }
    elSize: Integer;
    elType: ^PDynArrayTypeInfo;
    varType: Integer;
  end;

  ArrayEx<T> = record
    v: TArray<T>;
    CurrentLength: Integer;
    procedure add(Value: T);
  end;

procedure ArrayOfPointerSetLength(ptr: PPointer; const NewLength: NativeInt);
  procedure ArrayOfPointerClear(const ptr: PPointer);
    function __DynArrayRefCnt(const A: Pointer): Integer; inline;
    begin
      Result := PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.RefCnt;
    end;

  var
    p: Pointer;
  begin
    p := ptr^;
    if p <> nil then
    begin
      ptr^ := nil;
      if __DynArrayRefCnt(p) > 0 then
      begin
        if AtomicDecrement(PDynArrayRec(PByte(p) - SizeOf(TDynArrayRec))
          ^.RefCnt) = 0 then
        begin
          Dec(PByte(p), SizeOf(TDynArrayRec));
          SysFreeMem(p);
        end;
      end;
    end;
  end;

const
  elSize = SizeOf(Pointer);
var
  oldLength, minLength: NativeInt;
  neededSize: NativeInt;
  p: Pointer;
begin
  p := ptr^;
  neededSize := NewLength * elSize + SizeOf(TDynArrayRec);
  if p = nil then
    p := SysAllocMem(neededSize)
  else
  begin
    Dec(PByte(p), SizeOf(TDynArrayRec));
    oldLength := PDynArrayRec(p).Length;

    if PDynArrayRec(p).RefCnt = 1 then
      p := SysReallocMem(p, neededSize)
    else
    begin
      p := SysGetMem(neededSize);
      minLength := oldLength;
      if minLength > NewLength then
        minLength := NewLength;
      Move(PByte(ptr^)^, (PByte(p) + SizeOf(TDynArrayRec))^,
        minLength * elSize);
      ArrayOfPointerClear(ptr^);
    end;
    if NewLength > oldLength then
      FillChar((PByte(p) + SizeOf(TDynArrayRec) + elSize * oldLength)^,
        elSize * (NewLength - oldLength), 0);
  end;

  PDynArrayRec(p).RefCnt := 1;
  PDynArrayRec(p).Length := NewLength;
  Inc(PByte(p), SizeOf(TDynArrayRec));

  ptr^ := p;
end;

procedure ArrayEx<T>.add(Value: T);
const
  Plus = 21; // 32
var
  MaxLength: Integer;
begin
  if PDynArrayRec(v) = nil then
    MaxLength := 0
  else
    MaxLength := PDynArrayRec(NativeUInt(v) - SizeOf(TDynArrayRec)).Length;

  if CurrentLength >= MaxLength then
    ArrayOfPointerSetLength(Pointer(@v), MaxLength + Plus);

  v[CurrentLength] := Value;
  Inc(CurrentLength);
end;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

var
  arr: ArrayEx<Integer>;
  i: Integer;
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);

    for i := 0 to 50000000 do
      arr.add(i);

    Writeln(PrintTime(T));

    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



0.616766

Почему то, самый лучший результат, если по 21 выделять элемента. Ниже или выше.. Завывают медлительность
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762603
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Разница между твоим и моим кодом не в скорости а в том что мой "скрывает" grow буффер в массиве от компилятора.

И только.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762604
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Т.е. если твой Plus=21 то после добавления 5 элементов твой массив будет выглядеть так:
[0,1,2,3,4,0,0,0,0,0,0,... и так еще 11 раз]
а мой так:
[0,1,2,3,4] + "невидимый" буффер на 16 элементов.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762605
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как сам понимаешь полдьзоватся массивом в котором буффер "невидим" не в пример удобней.
При той же высокой скорости.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762608
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Смешной ты, ради вывода в дебаг-инфу настрочил столько бесполезного кода

Насчёт авторПри той же высокой скорости. не верю.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762613
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чёт я решил, сделать элегантный вывод !

Вот, он

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  ArrayEx<T> = record
    v: Pointer;
    CurrentLength, MaxLength: Integer;
    temp: TArray<T>;
    procedure add(Value: T);
    function GetIndex(i: Integer): T;
    function GetIndex2(i: Integer): T;
  end;

procedure ArrayEx<T>.add(Value: T);
type
  Test = array of T;
const
  elSize = SizeOf(Pointer);
  Plus = 48;
begin
  if MaxLength < CurrentLength then
  begin
    Inc(MaxLength, Plus);
    Dec(PByte(v), SizeOf(TDynArrayRec));
    v := SysReallocMem(v, MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));
  end
  else if v = nil then
  begin
    MaxLength := Plus;
    v := SysGetMem(MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));
  end;

  Test(v)[CurrentLength] := Value;

  Inc(CurrentLength);

  PPointer(@temp)^ := v;
  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;

function ArrayEx<T>.GetIndex(i: Integer): T;
begin
  if (i >= MaxLength) and (i <= CurrentLength) then
    Result := GetIndex2(i);
end;

function ArrayEx<T>.GetIndex2(i: Integer): T;
type
  Test = array of T;
begin
  Result := Test(v)[i];
end;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

var
  arr: ArrayEx<Integer>;
  i: Integer;
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);

    for i := 0 to 50000000 do
      arr.add(i);

    Writeln(PrintTime(T));

    for i := 0 to 100 do
      Writeln(arr.GetIndex2(i));

    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



Работает за 0.655926 сек
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762618
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всё. Из этого больше не выжить. 0.619081 сек

А так же добавил метод init что бы поля почистить перед стартом

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  ArrayEx<T> = record
    v: Pointer;
    CurrentLength, MaxLength: Integer;
    temp: TArray<T>;
    procedure init;
    procedure add(Value: T);
    function GetIndex(i: Integer): T;
    function GetIndex2(i: Integer): T;
  end;

procedure ArrayEx<T>.init;
begin
  v := nil;
  CurrentLength := 0;
  MaxLength := 0;
end;

procedure ArrayEx<T>.add(Value: T);
type
  Test = array of T;
const
  elSize = SizeOf(Pointer);
  Plus = 48;
begin
  if MaxLength < CurrentLength then
  begin
    Inc(MaxLength, Plus);
    Dec(PByte(v), SizeOf(TDynArrayRec));
    v := SysReallocMem(v, MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));

    PPointer(@temp)^ := v;
  end
  else if v = nil then
  begin
    MaxLength := Plus;
    v := SysGetMem(MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));

    PPointer(@temp)^ := v;
  end;

  Test(v)[CurrentLength] := Value;

  Inc(CurrentLength);

  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;

function ArrayEx<T>.GetIndex(i: Integer): T;
begin
  if (i >= MaxLength) and (i <= CurrentLength) then
    Result := GetIndex2(i);
end;

function ArrayEx<T>.GetIndex2(i: Integer): T;
type
  Test = array of T;
begin
  Result := Test(v)[i];
end;

// -----------------------

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

procedure Test; // Роли не играло, вынеся  в отдельную процедуру 
var
  arr: ArrayEx<Integer>;
  i: Integer;
begin
  with arr do
  begin

    init;

    for i := 0 to 50000000 do
      add(i);

    // for i := 0 to 100 do
    // Writeln(GetIndex2(i));
  end;
end;

var
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);
    Test;
    Writeln(PrintTime(T));
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762636
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдо,

ищи уже работу, впустую время тратишь
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762694
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatРади быстродействия в своем TArrayEx<T> = record даже SetLength захакал. :)

Реализовал то, что в FastMM делается и для массивов, и для строк
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762704
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2,

Как-то хреново делается. Ибо тормозит.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762711
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдо,

Интегеры добавляются здорово, ура! А теперь поудаляй из своего списка через одно поле. И желательно не integer, а какой-нибудь record <TProject> полей на 10-15.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762714
b0rk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если надо разово создать, например, миллион экземпляров, то массив рекордов будет быстрее, т.к. это один Alloc большого куска памяти (что гораздо быстрее миллиона маленьких) и нет миллиона вызовов конструктора. Eсли потом надо, например, сортировать список или добавлять/удалять элементы в середину, то с классами быстрее, т.к. это просто работа с указателем.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762720
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоСмешной ты, ради вывода в дебаг-инфу
Естессно не только ради дебаг инфы.

Например arr1.items+arr2.items будет корректно работать.


настрочил столько бесполезного кода"Столько" - это трочек 5? ;)
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762721
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
b0rk,

>>добавлять/удалять элементы в середину
и там и там не особо быстро

сортировку с записями не факт, если стандартную сортировку на месте не использовать, ИМХО она уже моветон
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762898
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Приятного знакомства
http://docwiki.embarcadero.com/RADStudio/Rio/en/Operator_Overloading_(Delphi)

А теперь магия удаления, алаба Кидабра

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function ArrayEx<T>.Remove(i: Integer): T;
begin
  Dec(MaxLength);
  System.Move(Test(v)[i + 1], Test(v)[i], (MaxLength - i) * SizeOf(elSize));

  Dec(CurrentLength);

  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;



Нет пустых элементов
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762906
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Удаление с добавлением отработало за 0.598266

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  ArrayEx<T> = record
    v: Pointer;
    CurrentLength, MaxLength: Integer;
    temp: TArray<T>;
    procedure init;
    procedure add(Value: T);
    function GetIndex(i: Integer): T;
    function GetIndex2(i: Integer): T;
    function Remove(i: Integer): T;

  type
    Test = array of T;

  const
    elSize = SizeOf(Pointer);
    Plus = 48;
  end;

procedure ArrayEx<T>.init;
begin
  v := nil;
  CurrentLength := 0;
  MaxLength := 0;
end;

procedure ArrayEx<T>.add(Value: T);
begin
  if MaxLength < CurrentLength then
  begin
    Inc(MaxLength, Plus);
    Dec(PByte(v), SizeOf(TDynArrayRec));
    v := SysReallocMem(v, MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));

    PPointer(@temp)^ := v;
  end
  else if v = nil then
  begin
    MaxLength := Plus;
    v := SysGetMem(MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));

    PPointer(@temp)^ := v;
  end;

  Test(v)[CurrentLength] := Value;

  Inc(CurrentLength);

  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;

function ArrayEx<T>.GetIndex(i: Integer): T;
begin
  if (i >= MaxLength) and (i <= CurrentLength) then
    Result := GetIndex2(i);
end;

function ArrayEx<T>.GetIndex2(i: Integer): T;
begin
  Result := Test(v)[i];
end;

function ArrayEx<T>.Remove(i: Integer): T;
begin
  Dec(MaxLength);
  System.Move(Test(v)[i + 1], Test(v)[i], (MaxLength - i) * SizeOf(elSize));

  Dec(CurrentLength);

  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;

// -----------------------

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

procedure Test; // Роли не играло, вынеся  в отдельную процедуру
var
  arr: ArrayEx<Integer>;
  i: Integer;
begin
  with arr do
  begin

    init;

    for i := 0 to 50000000 do
      add(i);

    Remove(50000000 - 2);

    add(50000000 - 2);
  end;
end;

var
  T: Int64;

begin
  try
    QueryPerformanceCounter(T);
    Test;
    Writeln(PrintTime(T));
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




То есть за 0.000001 понадобилось что бы удалить 50000000 - 2
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39762908
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Remove(100000); = 0.078513

Remove(1); = 0.085861
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763024
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдоrgreat,

Приятного знакомства
http://docwiki.embarcadero.com/RADStudio/Rio/en/Operator_Overloading_(Delphi)

А теперь магия удаления, алаба Кидабра

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function ArrayEx<T>.Remove(i: Integer): T;
begin
  Dec(MaxLength);
  System.Move(Test(v)[i + 1], Test(v)[i], (MaxLength - i) * SizeOf(elSize));

  Dec(CurrentLength);

  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;

Это ты точно мне писал?
Я про remove ничего не говорил.

Нет пустых элементов
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763025
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдоrgreat,

Приятного знакомства
http://docwiki.embarcadero.com/RADStudio/Rio/en/Operator_Overloading_(Delphi)

А теперь магия удаления, алаба Кидабра

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function ArrayEx<T>.Remove(i: Integer): T;
begin
  Dec(MaxLength);
  System.Move(Test(v)[i + 1], Test(v)[i], (MaxLength - i) * SizeOf(elSize));

  Dec(CurrentLength);

  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;


Нет пустых элементов


Это ты точно мне писал?
Я про remove ничего не говорил.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763031
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Нет, не тебе про удаления. Просто забыл ответ тому нажать
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763363
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдоrgreat,
Нет, не тебе про удаления. Просто забыл ответ тому нажать
А теперь для затравки заценим перформанс для какого-нибудь упрощённого TProject с полями
project_id

project_nr

internal_project_nr

project_name

start_date

company_id

im_company__name

im_office__name

service_line

cost_center

project_manager

external_project_nr

currency

contact_name

device_drug_name

disease

project_budget

closing_date

end_date
Топикстартер хотел же именно <TProject> ;-)
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763454
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimonka,

My - ArrayEx :: TForm -> 0.697550

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure Test;
var
  arr: ArrayEx<TForm>;
  i: Integer;
  v: TForm;
begin
  v := TForm.Create(nil);
  with arr do
  begin
    init;

    for i := 0 to 50000000 do
      add(v);
  end;
end;




TList :: TForm -> 0.798694
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure Test;
var
  arr: TList;
  i: Integer;
  v: TForm;
begin
  v := TForm.Create(nil);
  arr := TList.Create;
  with arr do
  begin

    for i := 0 to 50000000 do
      add(v);
  end;
end;




Remove 50000000 div 2

My - ArrayEx :: TForm -> 0.038616
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
procedure Test;
var
  T: Int64;
  arr: ArrayEx<TForm>;
  i: Integer;
  v: TForm;
begin
  v := TForm.Create(nil);
  with arr do
  begin
    init;
    for i := 0 to 50000000 do
      add(v);
    QueryPerformanceCounter(T);
    Remove(50000000 div 2);
    Writeln(PrintTime(T));
  end;
end;




TList :: TForm -> 0.040716
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
procedure Test;
var
  T: Int64;
  arr: TList;
  i: Integer;
  v: TForm;
begin
  v := TForm.Create(nil);
  arr := TList.Create;
  with arr do
  begin
    for i := 0 to 50000000 do
      add(v);

    QueryPerformanceCounter(T);
    Delete(50000000 div 2);
    Writeln(PrintTime(T));
  end;
end;

...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763463
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сейчас понял, что нужно было использовать TList от System.Generics.Collections

Извиняюсь, извиняюсь! Что был глуп и слеп

0.993732
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure Test;
var
  arr: TList<TForm>;
  i: Integer;
  v: TForm;
begin
  v := TForm.Create(nil);
  arr := TList<TForm>.Create;
  with arr do
  begin
    for i := 0 to 50000000 do
      add(v);

  end;
end;



В общем мой ArrayEx выигрывает 0.296182

По удалению тоже самое что и у обычного TList плюс минус 0.0001
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763466
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и что бы закрепить, тест ещё на integer

0.968195
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure Test;
var
  arr: TList<Integer>;
  i: Integer;
begin
  arr := TList<Integer>.Create;
  with arr do
  begin
    for i := 0 to 50000000 do
      add(i);
  end;
end;



Когда мой даёт 0.585812
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763699
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдо,

Вангую, что если нотификацию убрать (которой у тебя, к слову, нет), то будет примерно столько же.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763718
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon,

Что убрать? Создание ? Это не влияет.

И нет, не будет. Там много разных вызовов функций, проверок и так далее. Так что - не будет.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763723
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гирлионайльдо,

Ну ландо, крутой массив. Осталось только обвязать его всем, чем положено: .Sort, .IndexOf, For in, копированием, владением объектами, совместимостью с TList итд и ВСЁ! можно использовать..
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763727
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При вызове add от TList<Integer>

Он вызывает
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
function TListHelper.InternalAdd4(const Value): Integer;
begin
  InternalGrowCheck(FCount + 1);
  Result := FCount;
  PCardinal(FItems^)[FCount] := Cardinal(Value);
  Inc(FCount);
  FNotify(Value, cnAdded);
end;



Вызывает
Код: pascal
1.
2.
3.
4.
5.
6.
7.
procedure TListHelper.InternalGrowCheck(ANewCount: Integer);
begin
  if ANewCount > DynArraySize(FItems^) then
    InternalGrow(ANewCount)
  else if ANewCount < 0 then
    OutOfMemoryError;
end;



На функцию DynArraySize можно не обращать внимания, она inline
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure TListHelper.InternalGrow(ANewCount: Integer);
var
  NewCount: Integer;
begin
  NewCount := DynArraySize(FItems^);
  if NewCount = 0 then
    NewCount := ANewCount
  else
    repeat
      NewCount := NewCount * 2;
      if NewCount < 0 then
        OutOfMemoryError;
    until NewCount >= ANewCount;
  InternalSetCapacity(NewCount);
end;



Код: pascal
1.
2.
3.
4.
procedure TListHelper.InternalSetCapacity(Value: NativeInt);
begin
  DynArraySetLength(FItems^, FTypeInfo, 1, @Value);
end;



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
procedure DynArraySetLength(var a: Pointer; typeInfo: Pointer; dimCnt: NativeInt; lengthVec: PNativeInt);
var
  i,j: NativeInt;
  newLength, oldLength, minLength: NativeInt;
  elSize: NativeInt;
  t: PDynArrayTypeInfo;
  ElTypeInfo: Pointer;
  neededSize: NativeInt;
  p, pp: Pointer;
begin
  p := a;

  // Fetch the new length of the array in this dimension, and the old length
  newLength := lengthVec^;
  if newLength <= 0 then
  begin
    if newLength < 0 then
      Error(reRangeError);
    _DynArrayClear(a, typeInfo);
    exit;
  end;

  oldLength := 0;
  if p <> nil then
  begin
    Dec(PByte(p), SizeOf(TDynArrayRec));
    oldLength := PDynArrayRec(p).Length;
  end;

  // Calculate the needed size of the heap object
  t := PDynArrayTypeInfo( PByte(typeInfo) + PDynArrayTypeInfo(typeInfo).name );
  elSize := t.elSize;
  if t.elType <> nil then
    ElTypeInfo := t.elType^
  else
    ElTypeInfo := nil;
  neededSize := newLength*elSize;
  if neededSize div newLength <> elSize then
    Error(reRangeError);
  Inc(neededSize, SizeOf(TDynArrayRec));
  if neededSize < 0 then
    Error(reRangeError);

  // If the heap object isn't shared (ref count = 1), just resize it. Otherwise, we make a copy
  if (p = nil) or (PDynArrayRec(p).RefCnt = 1) then
  begin
    pp := p;
{$IF not Defined(WEAKREF)}
    if (newLength < oldLength) and (ElTypeInfo <> nil) then
      FinalizeArray(PByte(p) + SizeOf(TDynArrayRec) + newLength*elSize, ElTypeInfo, oldLength - newLength);
    ReallocMem(pp, neededSize);
{$ELSE}
    if (ElTypeInfo <> nil) then
    begin
      if SysHasWeakRef(PTypeInfo(ElTypeInfo)) then
      begin
        if newLength < oldLength then
          minLength := newLength
        else
          minLength := oldLength;
        GetMem(pp, neededSize);
        FillChar((PByte(pp) + SizeOf(TDynArrayRec))^, minLength * elSize, 0);
        if p <> nil then
        begin
          MoveArray(PByte(pp) + SizeOf(TDynArrayRec),
                     PByte(p) + SizeOf(TDynArrayRec), ElTypeInfo, minLength);
          if newLength < oldLength then
            FinalizeArray(PByte(p) + SizeOf(TDynArrayRec) + newLength*elSize, ElTypeInfo, oldLength - newLength);
          FreeMem(p);
        end;
      end
      else
      begin
        if (newLength < oldLength) then
          FinalizeArray(PByte(p) + SizeOf(TDynArrayRec) + newLength*elSize, ElTypeInfo, oldLength - newLength);
        ReallocMem(pp, neededSize);
      end;
    end
    else
      ReallocMem(pp, neededSize);
{$ENDIF}
    p := pp;
  end
  else
  begin
    GetMem(p, neededSize);
    minLength := oldLength;
    if minLength > newLength then
      minLength := newLength;
    if ElTypeInfo <> nil then
    begin
      FillChar((PByte(p) + SizeOf(TDynArrayRec))^, minLength*elSize, 0);
      __CopyArray(PByte(p) + SizeOf(TDynArrayRec), a, ElTypeInfo, minLength)
    end
    else
      Move(PByte(a)^, (PByte(p) + SizeOf(TDynArrayRec))^, minLength*elSize);
    _DynArrayClear(a, typeInfo);
  end;

  // The heap object will now have a ref count of 1 and the new length
  PDynArrayRec(p).RefCnt := 1;
  PDynArrayRec(p).Length := newLength;
  Inc(PByte(p), SizeOf(TDynArrayRec));

  // Set the new memory to all zero bits
  if newLength > oldLength then
    FillChar((PByte(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0);

  // Take care of the inner dimensions, if any
  if dimCnt > 1 then
  begin
    Inc(lengthVec);
    Dec(dimCnt);
    i := 0;
    try
      while i < newLength do
        begin
          DynArraySetLength(PPointerArray(p)[i], ElTypeInfo, dimCnt, lengthVec);
          Inc(i);
        end;
    except
      // Free arrays on exception
      for j := 0 to i  do
        _DynArrayClear(PPointerArray(p)[j], ElTypeInfo);
      _DynArrayClear(p, typeInfo);
      raise;
    end;
  end;
  a := p;
end;

...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763731
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimonka,

Можно, но нужно ли? Всё же выигрыш в 0.3 - 0.4 сек не такой уж и важный
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763748
Фотография Dimonka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоDimonka,
Можно, но нужно ли? Всё же выигрыш в 0.3 - 0.4 сек не такой уж и важный
Так о чём и речь. Для каких-то специализированных целей можно ну очень специализированный список самому накалякать, а для универсального использования TList за глаза сойдёт.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763873
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоНу и что бы закрепить, тест ещё на integer
0.968195
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure Test;
var
  arr: TList<Integer>;
  i: Integer;
begin
  arr := TList<Integer>.Create;
  with arr do
  begin
    for i := 0 to 50000000 do
      add(i);
  end;
end;

Когда мой даёт 0.585812Давай, запили ещё тест, когда заполняются несколько листов одновременно.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763879
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bred eFeM
ГирлионайльдоНу и что бы закрепить, тест ещё на integer
0.968195
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure Test;
var
  arr: TList<Integer>;
  i: Integer;
begin
  arr := TList<Integer>.Create;
  with arr do
  begin
    for i := 0 to 50000000 do
      add(i);
  end;
end;

Когда мой даёт 0.585812Давай, запили ещё тест, когда заполняются несколько листов одновременно.

Твой сарказм уже не уместен.

Могу привести, один важный факт.

Моя реализация, на 50000000 элементов, потребляет 197 озу.

Когда TList<Integer> потребляет на такое же количество, уже 262 озу

То есть, в 65 мб больше
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763894
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Твой сарказм уже не уместенпочему сарказм, интересно:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
program Project7;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils, System.Generics.Collections;

type
  PDynArrayRec = ^TDynArrayRec;

  TDynArrayRec = packed record
{$IFDEF CPU64BITS}
    _Padding: Integer; // Make 16 byte align for payload..
{$ENDIF}
    RefCnt: Integer;
    Length: NativeInt;
  end;

  ArrayEx<T> = record
    v: Pointer;
    CurrentLength, MaxLength: Integer;
    temp: TArray<T>;
    procedure add(Value: T);
    function GetIndex(i: Integer): T;
    function GetIndex2(i: Integer): T;
  end;

procedure ArrayEx<T>.add(Value: T);
type
  Test = array of T;
const
  elSize = SizeOf(Pointer);
  Plus = 48;
begin
  if MaxLength < CurrentLength then
  begin
    Inc(MaxLength, Plus);
    Dec(PByte(v), SizeOf(TDynArrayRec));
    v := SysReallocMem(v, MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));
  end
  else if v = nil then
  begin
    MaxLength := Plus;
    v := SysGetMem(MaxLength * elSize + SizeOf(TDynArrayRec));
    Inc(PByte(v), SizeOf(TDynArrayRec));
  end;

  Test(v)[CurrentLength] := Value;

  Inc(CurrentLength);

  PPointer(@temp)^ := v;
  PDynArrayRec(NativeUInt(temp) - SizeOf(TDynArrayRec)).Length := CurrentLength;
end;

function ArrayEx<T>.GetIndex(i: Integer): T;
begin
  if (i >= MaxLength) and (i <= CurrentLength) then
    Result := GetIndex2(i);
end;

function ArrayEx<T>.GetIndex2(i: Integer): T;
type
  Test = array of T;
begin
  Result := Test(v)[i];
end;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

const
  N = 250000; //
var
  arr: array [0..1023] of  ArrayEx<Integer>;
  arra:array [0..1023] of  TList<Integer>;
  i,j: Integer;
  T: Int64;
begin
  try
  QueryPerformanceCounter(T);
    for i := 0 to N do
      for j := Low(arr) to High(arr)
       do arr[j].add(i);
  Writeln('ArrayEx<Integer>.Add '+PrintTime(T));

  QueryPerformanceCounter(T);
    for j := Low(arr) to High(arr) do
     FreeMem(PByte(arr[j].v) - SizeOf(TDynArrayRec) );
  Writeln('ArrayEx<Integer>.Free '+PrintTime(T));

  //

  QueryPerformanceCounter(T);
    for j := Low(arra) to High(arra) do
     arra[j]:= TList<Integer>.Create;
    for i := 0 to N do
     for j := Low(arra) to High(arra) do
       arra[j].add(i);
  Writeln('TList<Integer>.Add '+PrintTime(T));

  QueryPerformanceCounter(T);
    for j := Low(arra) to High(arra) do
      FreeMem( PByte( PPointer(PByte(arra[j]) + 8 + SizeOf(TListHelper))^) - SizeOf(TDynArrayRec));
  Writeln('TList<Integer>."Free" '+PrintTime(T));

  //

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
// x86
// #1
ArrayEx<Integer>.Add 7.383058
ArrayEx<Integer>.Free 0.251668
TList<Integer>.Add 7.317250
TList<Integer>.Free 0.231141
// #2
ArrayEx<Integer>.Add 7.425692
ArrayEx<Integer>.Free 0.252234
TList<Integer>.Add 7.276288
TList<Integer>.Free 0.232548
// #3
ArrayEx<Integer>.Add 7.362651
ArrayEx<Integer>.Free 0.252028
TList<Integer>.Add 7.353942
TList<Integer>.Free 0.231327

// x64
// #1
ArrayEx<Integer>.Add 8.883673
ArrayEx<Integer>.Free 0.368604
TList<Integer>.Add 8.114259
TList<Integer>."Free" 0.237586
// #2
ArrayEx<Integer>.Add 8.921077
ArrayEx<Integer>.Free 0.367548
TList<Integer>.Add 8.247885
TList<Integer>."Free" 0.235625
// #3
ArrayEx<Integer>.Add 8.986561
ArrayEx<Integer>.Free 0.367565
TList<Integer>.Add 8.102526
TList<Integer>."Free" 0.236061
в чем сила, брат?
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763898
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bred eFeM,

Доверяй, но проверяй :) У тебя проблема в циклах!


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
TList:
Init: 0.000154
Add: 4.669602
Free: 2.271111

TArrayEx:
Init: 0.000089
Add: 3.025231
Free: 0.143431



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils, FastListArray, System.Generics.Collections;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

procedure Start(func: Pointer);
var
  T: Int64;
type
  call = procedure();
begin
  QueryPerformanceCounter(T);
  call(func)();
  Writeln(PrintTime(T));
end;

const
  N = 250000; //

var
  arr: array [0 .. 1023] of TArrayEx<Integer>;
  arra: array [0 .. 1023] of TList<Integer>;
  i, j: Integer;
  T: Int64;

procedure TListTestInit;
begin
  for i := Low(arra) to High(arra) do
    arra[i] := TList<Integer>.Create;
end;

procedure TArrayExTestInit;
begin
  for i := Low(arr) to High(arr) do
    arr[i].init;
end;

procedure TListTestAdd;
begin
  for j := Low(arra) to High(arra) do
    for i := 0 to N do
      arra[j].add(i);
end;

procedure TArrayExTestAdd;
begin
  for j := Low(arr) to High(arr) do
    for i := 0 to N do
      arr[j].add(i);
end;

procedure TListTestFree;
begin
  for j := Low(arra) to High(arra) do
    arra[j].Free;
end;

procedure TArrayExTestFree;
begin
  for j := Low(arr) to High(arr) do
    arr[j].Free;
end;

begin
  try
    Writeln('TList: ');
    Writeln('Init: ');
    Start(@TListTestInit);

    Writeln('Add: ');
    Start(@TListTestAdd);

    Writeln('Free: ');
    Start(@TListTestFree);

    Writeln('TArrayEx: ');
    Writeln('Init: ');
    Start(@TArrayExTestInit);

    Writeln('Add: ');
    Start(@TArrayExTestAdd);

    Writeln('Free: ');
    Start(@TArrayExTestFree);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39763963
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоBred eFeM,

Доверяй, но проверяй :) У тебя проблема в циклах!эту проблему он кажется и тестит

Bred eFeMДавай, запили ещё тест, когда заполняются несколько листов одновременно.а не последовательно
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39764221
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоДоверяй, но проверяй :) У тебя проблема в циклах! о, спасибо, только это уже у тебя проблемы!
Код: pascal
1.
2.
3.
4.
5.
procedure TListTestFree; // Free*
begin
  for j := Low(arra) to High(arra) do
    FreeMem( PByte( PPointer(PByte(arra[j]) + 8 + SizeOf(TListHelper))^) - SizeOf(TDynArrayRec)); // => FreeMem (@TList<>.FList - SizeOf(TDynArrayRec))
end;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
x86
TList:  #1          #2          #3
Init:   0.000174    0.000167    0.000175
Add:    3.298258    3.290902    3.280236
Free*:  0.206021    0.205084    0.205407
TArrayEx:
Init:   0.000058    0.000058    0.000064
Add:    3.951568    3.952066    3.951261
Free:   0.215579    0.215126    0.215459

x64
TList:  #1          #2          #3
Init:   0.000192    0.000182    0.000179
Add:    3.247844    3.236234    3.237612
Free*:  0.214759    0.220769    0.217551
TArrayEx:
Init:   0.000083    0.000089    0.000085
Add:    4.562433    4.430180    4.417473
Free:   0.362171    0.362515    0.363038

Если кроме твоего одного ArrayEx никто память не дёргает, то возможно это и быстрее, но в рабочем режиме частые реаллоки хуже, что мы и видим при тесте.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39764284
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bred eFeM,

Мне кажется ты врёшь с тестами
Нинадо так.

Я же сейчас протестировал на i3 и там тоже выигрыш как и на core 2 duo e8400.
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39764288
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тот код совершенно никак не может быть быстрее, по причине того, что там дёргается куча вызовов. А у меня в процедуре добавление только 1 проверка, которая срабатывает раз в год для того же SysReallocMem

По этому, делаю вывод что ты врунишка)
...
Рейтинг: 0 / 0
Список классов vs списка записей - в чем преимущество?
    #39764363
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоТот код совершенно никак не может быть быстрее Ну, проси форумчан потестить - если истина дороже.

зы - i5-2400, Dx10.2.3
...
Рейтинг: 0 / 0
63 сообщений из 63, показаны все 3 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Список классов vs списка записей - в чем преимущество?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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