Ускорение работы с listbox, combobox, memo ...

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

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

Ускорение работы с listbox, combobox, memo ...

Сообщение AMD » 09.02.2008 08:05:05

Кстати очень полезная вещь!!!

If you use a Lazarus component like a ListBox, Memo, TreeList, ListView,... and you add or modify a lot of items (lines, nodes,...), the component's performance becomes very slow. This is due to the fact that after each change, it is redrawn on the screen.

Thus, modifying 10000 items of a ListBox causes 10000 redraws, and that takes from several seconds to several minutes, depending on the computer's speed and the complexity of the process. Imagine how slow it can become if the process involves inserting, deleting, modifying and swapping many thousands of items.

But you can speed up things enormously with the following tip:

Call BeginUpdate before making the changes to the items. When all changes are complete, call EndUpdate to show the changes on screen. BeginUpdate and EndUpdate prevent excessive redraws and speed up processing time when items are added, deleted, or inserted.

Here's a simple source code example for using this technique with a ListBox:

ListBox1.Items.BeginUpdate;
for i := 1 to 10000 do
ListBox1.Items.Add('abcd');
ListBox1.Items.EndUpdate;

To give you an idea of the improvement, we timed the code above (your PC may be faster or slower):
» without the BeginUpdate/EndUpdate lines: 4.3 seconds...
» with BeginUpdate/EndUpdate: 0.1 seconds, that's 43 times faster!

Here's a source code example for using this technique with a Memo:

Memo1.Lines.BeginUpdate;
for i := 1 to 5000 do
Memo1.Lines.Add('abcd');
Memo1.Lines.EndUpdate;

» without BeginUpdate/EndUpdate: 25 seconds...
» with BeginUpdate/EndUpdate: 0.6 seconds!
AMD
постоялец
 
Сообщения: 189
Зарегистрирован: 23.01.2008 22:25:25
Откуда: Кишинев

Сообщение debi12345 » 09.02.2008 12:07:20

This is due to the fact that after each change, it is redrawn on the screen.

Да, для не БД-виджетов этот запрет синхронной перерисовки очень полезен, потому что узнать без помощи самого программиста, когда начинается и когда закачивается заполнение списка - невозможно (в отличие от БД-виджетов, для которых для этих дел автоматически вызываются DisableControls/EnableControls связанного датасета).
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение Maxx_ir » 24.02.2008 21:49:25

:( Хм.. Проверял следующий кусок на Lazarus v.0.9.24 под Мандрива, Debiah (GTK) и WinXp
>>
ListBox1.Items.BeginUpdate;
for i := 0 to 10000 do
begin
ListBox1.Items.Add(IntToStr(i));
end;
ListBox1.Items.EndUpdate;
>>
результат для Linux удручающий - 15 - 20 сек
WinXp - практически мнгновенно
Аватара пользователя
Maxx_ir
новенький
 
Сообщения: 12
Зарегистрирован: 24.02.2008 20:52:00
Откуда: Тольятти

Сообщение AMD » 24.02.2008 22:20:09

А если попробовать

ListBox1.Visible=False;


ListBox1.Visible=True;


Поможет?
AMD
постоялец
 
Сообщения: 189
Зарегистрирован: 23.01.2008 22:25:25
Откуда: Кишинев

Сообщение Maxx_ir » 24.02.2008 22:33:59

AMD писал(а):А если попробовать

ListBox1.Visible=False;


ListBox1.Visible=True;


Поможет?


Пробовал не помогает, мало того заметил что и ScrollBar не отображется
ListBox1.Items.Add(IntToStr(i)); заменял на
ListBox1.Items.LoadFromFile('some.txt') где размер текстового файла ~ 50 кб - результат тот же :(
Аватара пользователя
Maxx_ir
новенький
 
Сообщения: 12
Зарегистрирован: 24.02.2008 20:52:00
Откуда: Тольятти

Сообщение debi12345 » 24.02.2008 22:46:05

Вы что-то не так меряли. Или со сверхтяжелым тулкитом вроде GTK2.

У меня прорисовка данных со связкой полей :

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

procedure tmainfo.created(const sender: TObject);
var
i: integer;
s: msestring;
begin
for i:= 1 to 10000 do begin
  s:= 'Item '+ inttostr(i);
  lbuf.addrow([i],[s],[]);
end;
end;


занимает 1.5 секунды (причем на стареньком Р3-700)
100.000 рисуются 15 секунд при первом открытии списка, потом - практически мгновенно.


Загрузка миллиона записей без связки полей :

Код: Выделить всё
begin
for i:= 1 to 1000000 do begin
  arr:= opentodynarraym( [ 'Item ' + inttostr(i)] );
  tenumedit1.addrow(arr); 
end;
end;


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

Сообщение Maxx_ir » 24.02.2008 22:58:22

Вы попробуйте именно TListBox

>>
ListBox1.Items.BeginUpdate;
for i := 0 to 10000 do
begin
ListBox1.Items.Add(IntToStr(i));
end;
ListBox1.Items.EndUpdate;
>>

Да нет там никакого GTK2!
Проверял Mandriva2005 - GTK,
Debiah - DSL 3.4.1 - это чудо вообще не требовательно к ресурсам полный дистр 50 mb -это и есть целевая ось для embed системы, не проверил на списках > 1000 строк а тут такие грабли :(
Аватара пользователя
Maxx_ir
новенький
 
Сообщения: 12
Зарегистрирован: 24.02.2008 20:52:00
Откуда: Тольятти

Сообщение Attid » 25.02.2008 12:24:24

в трекер.
а пользователь точно нормально сможет выбрать из списка в 10000 ? =)
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение AMD » 25.02.2008 13:22:22

Attid писал(а):в трекер.
а пользователь точно нормально сможет выбрать из списка в 10000 ? =)


Кто знает может у него и фильтр задуман
AMD
постоялец
 
Сообщения: 189
Зарегистрирован: 23.01.2008 22:25:25
Откуда: Кишинев

Сообщение debi12345 » 25.02.2008 13:26:02

Attid писал(а):в трекер.
а пользователь точно нормально сможет выбрать из списка в 10000 ? =)

Как ни странно - без проблем (мне это тоже стало интересно). Даже с миллионом записей:) К тому же список подстраивается под ручной ввод в текстовой зоне.
Главное - чтобы не тормозило при каждом раскрытии списка.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение Attid » 25.02.2008 13:35:37

а там вообще страшная бага, у меня кроме того что висит 15 секунд так потом там еще не все значения видно =)

так что и смотреть нечего, бага там.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение alexs » 25.02.2008 19:42:16

Ибо нефиг такие списки делать :-).
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Сообщение Attid » 25.02.2008 20:23:39

alexs писал(а):Ибо нефиг такие списки делать Smile.

угу, а до 2000 отрабатывает все нормально =)
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение Maxx_ir » 25.02.2008 22:07:41

alexs писал(а):Ибо нефиг такие списки делать :-).

Это понятно нефиг - нафиг
А что здесь в топике написано ?

Here's a simple source code example for using this technique with a ListBox:

ListBox1.Items.BeginUpdate;
for i := 1 to 10000 do
ListBox1.Items.Add('abcd');
ListBox1.Items.EndUpdate;

To give you an idea of the improvement, we timed the code above (your PC may be faster or slower):
» without the BeginUpdate/EndUpdate lines: 4.3 seconds...
» with BeginUpdate/EndUpdate: 0.1 seconds, that's 43 times faster!

» without BeginUpdate/EndUpdate: 25 seconds...
» with BeginUpdate/EndUpdate: 0.6 seconds

Брехня не работает :D
Аватара пользователя
Maxx_ir
новенький
 
Сообщения: 12
Зарегистрирован: 24.02.2008 20:52:00
Откуда: Тольятти

Сообщение Attid » 25.02.2008 23:23:23

да говорят же бага еще под вендой проверю и запостю.

кто нибуть под линем еще может подтвердить? по поводу того что не все под гтк1 отображается ? например на 5000 записей вижу только на тысячу с конца.
а на 3000 в листе только 20 записей.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

След.

Вернуться в Lazarus

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

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

Рейтинг@Mail.ru