Скорость заполнения BufDataset и TObjectList

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

Скорость заполнения BufDataset и TObjectList

Сообщение Sharfik » 23.03.2024 12:00:16

Есть класс на основе TObjectList и TBufDataset. Заполняю их от 0 до 25000 и получаю вот такие результаты по скорости
Заполнение
ObjectList Выполнено за:4,4246 сек.
BufDataset1 Выполнено за:8,5468 сек.
//Построчная математическая операция
ObjectList Выполнено за:0,8511 сек.
BufDataset1 Выполнено за:0,0460 сек.
//Математическая операция в случайном порядке
ObjectList Выполнено за:12,3523 сек.
BufDataset1 Выполнено за:0,8177 сек.


Математические операции порадовали и удивили, ибо при ручной отрисовке RxDBGrid мне показалось что работа с BufDataset дольше, чем тоже самое но на основе классов. А тут деление, сложение быстрее проходит. А вот заполнение буфера по скорости в два раза медленнее. На малых объемах это не заметно, но чем больше строк, тем больше разрыв.

Внимание, вопрос - а есть какие то ухищрения это исправить?

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  i:integer;
  aObject:TAssiBasicObjectItem;
  iCounterPerSec,C1,C2 :TLargeInteger;
begin
  randomize;

  QueryPerformanceFrequency(iCounterPerSec);
  QueryPerformanceCounter(C1);
  for i := 0 to SpinEdit1.Value - 1 do
  begin
      aObject:=TAssiBasicObjectItem.Create;
      aObject.SetParameter('id',i);
      aObject.SetParameter('name','name');
      aObject.SetParameter('value',i);
      Collection.add(aObject);
  end;
  QueryPerformanceCounter(C2);
  memo1.Lines.Add('ObjectList Выполнено за:'+FormatFloat('0.0000', (C2 - C1) / iCounterPerSec) + ' сек.');

  BufDataset1.DisableControls;

  QueryPerformanceFrequency(iCounterPerSec);
  QueryPerformanceCounter(C1);
  for i := 0 to SpinEdit1.Value - 1 do
  begin
      BufDataset1.Append;
      BufDataset1.FieldByName('id').AsInteger:=i;
      BufDataset1.FieldByName('name').AsString:='name';
      BufDataset1.FieldByName('value').AsInteger:=i;
      BufDataset1.Post;
  end;
  QueryPerformanceCounter(C2);
  BufDataset1.EnableControls;
  memo1.Lines.Add('BufDataset1 Выполнено за:'+FormatFloat('0.0000', (C2 - C1) / iCounterPerSec) + ' сек.');

end;


Код: Выделить всё
procedure TForm1.Button2Click(Sender: TObject);
var
  e1,e2,
  i:integer;
  aObject:TAssiBasicObjectItem;
  //test
  iCounterPerSec,C1,C2 :TLargeInteger;
begin
  randomize;
  e1:=0;
  QueryPerformanceFrequency(iCounterPerSec);
  QueryPerformanceCounter(C1);
  for i := 0 to Collection.Count - 1 do
  begin
      aObject:=Collection.Items[i];
      e2:=aObject.GetParameter('value');
      e1:=e1+(e2 div 2);
  end;
  QueryPerformanceCounter(C2);
  memo1.Lines.Add('ObjectList Выполнено за:'+FormatFloat('0.0000', (C2 - C1) / iCounterPerSec) + ' сек.');

  BufDataset1.DisableControls;
  e1:=0;

  QueryPerformanceFrequency(iCounterPerSec);
  QueryPerformanceCounter(C1);
  BufDataset1.First;
  while not BufDataset1.EOF do
  begin
      e2:=BufDataset1.FieldByName('value').AsInteger;
      e1:=e1+(e2 div 2);
      BufDataset1.Next;
  end;
  QueryPerformanceCounter(C2);
  BufDataset1.EnableControls;
  memo1.Lines.Add('BufDataset1 Выполнено за:'+FormatFloat('0.0000', (C2 - C1) / iCounterPerSec) + ' сек.');

end;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

Re: Скорость заполнения BufDataset и TObjectList

Сообщение grot » 23.03.2024 12:26:28

Навскидку, попробуйте варианты с :

1) BufDataset1.UniDirectional:= True; // уберет лишнюю буферизацию/требование к памяти...

2) замените Dataset.FieldByName(...).As... -- на -- Dataset.Fields[...].As... ( еще попробуйте вариант с .Value )

3) запишите в переменную значение SpinEdit1.Value - 1 и ее используйте в цикле

4) если есть, то отключить индексы, фильтры, (сортировки ?) ...

Добавлено спустя 8 минут 9 секунд:
5) попробовать TDataSet.AppendRecord
grot
новенький
 
Сообщения: 75
Зарегистрирован: 13.02.2010 16:33:03

Re: Скорость заполнения BufDataset и TObjectList

Сообщение stikriz11 » 23.03.2024 14:19:18

Тормоза этого датасета на вставку, скорее всего, проистекают из-за вот этого кода:
function TDoubleLinkedBufIndex.GetRecNo: Longint;
var ARecord : PBufRecLinkItem;
begin
ARecord := FCurrentRecBuf;
Result := 1;
while ARecord <> FFirstRecBuf do
begin
inc(Result);
ARecord := ARecord[IndNr].prior;
end;
end;
stikriz11
постоялец
 
Сообщения: 114
Зарегистрирован: 04.09.2023 15:54:19

Re: Скорость заполнения BufDataset и TObjectList

Сообщение Sharfik » 23.03.2024 18:15:58

grot писал(а):1) BufDataset1.UniDirectional:= True;

тогда он становиться только для чтения
grot писал(а):2) замените Dataset.FieldByName(...).As... -- на -

вообще убрал заполнение - та же скорость
grot писал(а):3) запишите в переменную значение SpinEdit1.Value - 1 и ее используйте в цикле

это не влияет на скорость, для обоих методов хранения цикл одинаковый
grot писал(а):5) попробовать TDataSet.AppendRecord

тот же результат
stikriz11 писал(а):Тормоза этого датасета на вставку, скорее всего, проистекают из-за вот этого кода:

вот тут мне пришла мысль, а если сравнить MemDataset1 и BufDataset1. Я некогда не понимал в них разницу, и найти вразумительно описание отличий тоже не получалось.
и вот что вышло

//Заполнение
ObjectList Выполнено за:1,8943 сек.
BufDataset1 Выполнено за:2,3572 сек.
MemDataset1 Выполнено за:0,1115 сек.
//Подряд суммирование
ObjectList Выполнено за:0,4083 сек.
e1=156237500
BufDataset1 Выполнено за:0,0239 сек.
e1=156237500
MemDataset1 Выполнено за:0,0255 сек.
e1=156237500
//Суммирование случайных объектов
ObjectList Выполнено за:7,3425 сек.
e1=345046
BufDataset1 Выполнено за:0,3642 сек.
e1=330835
MemDataset1 Выполнено за:0,3492 сек.
e1=299218

:D
Очень интересный результат. Хотя, кажется(не помню) были какие то отличия в части Load/Save какой то датасет что то не умел. То ли в файл, то ли в stream писать.читать.

Надо будет копать. В любом случае всем спасибо, за идеи.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

Re: Скорость заполнения BufDataset и TObjectList

Сообщение alexs » 25.03.2024 16:57:34

При работе с наследниками DataSet самый быстрый метод обращения к полям - это создать постоянные поля - в дизайнере - дваждый щёлкнуть по компоненте и добавить поля.
И в последствии работать с ними.
Потом по скорости будет Dataset.Fields[...].As - тут оверхеад идёт на обращении по индексу к списоку полей
и самый медленный - FieldByName - там просто тупой перебор и сравнение по имени поля.
Field.Value - тоже не лучший вариант - затраты будут на конвертацию в Variant и обратно. Лучше всёже явно правильно типы указывать - AsInteger/AsString
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Скорость заполнения BufDataset и TObjectList

Сообщение Sharfik » 26.03.2024 02:18:01

Задержку на создании это увы не исправит)
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

Re: Скорость заполнения BufDataset и TObjectList

Сообщение alexs » 26.03.2024 10:55:26

Если учесть что DataSet обычно хранит свои данные в наследнике от списоков - то естественно типизированные объекты будут быстрее. За универсальность надо платить...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь


Вернуться в Базы данных

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

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

Рейтинг@Mail.ru
cron