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

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

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

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

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

Сообщение AMD »

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

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

Сообщение debi12345 »

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

Да, для не БД-виджетов этот запрет синхронной перерисовки очень полезен, потому что узнать без помощи самого программиста, когда начинается и когда закачивается заполнение списка - невозможно (в отличие от БД-виджетов, для которых для этих дел автоматически вызываются DisableControls/EnableControls связанного датасета).
Аватара пользователя
Maxx_ir
новенький
Сообщения: 12
Зарегистрирован: 24.02.2008 19:52:00
Откуда: Тольятти
Контактная информация:

Сообщение Maxx_ir »

:( Хм.. Проверял следующий кусок на 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 - практически мнгновенно
AMD
постоялец
Сообщения: 189
Зарегистрирован: 23.01.2008 21:25:25
Откуда: Кишинев

Сообщение AMD »

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

ListBox1.Visible=False;


ListBox1.Visible=True;


Поможет?
Аватара пользователя
Maxx_ir
новенький
Сообщения: 12
Зарегистрирован: 24.02.2008 19:52:00
Откуда: Тольятти
Контактная информация:

Сообщение Maxx_ir »

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

ListBox1.Visible=False;


ListBox1.Visible=True;


Поможет?


Пробовал не помогает, мало того заметил что и ScrollBar не отображется
ListBox1.Items.Add(IntToStr(i)); заменял на
ListBox1.Items.LoadFromFile('some.txt') где размер текстового файла ~ 50 кб - результат тот же :(
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

Вы что-то не так меряли. Или со сверхтяжелым тулкитом вроде 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 и менее - практически мгновенно.
Аватара пользователя
Maxx_ir
новенький
Сообщения: 12
Зарегистрирован: 24.02.2008 19:52:00
Откуда: Тольятти
Контактная информация:

Сообщение Maxx_ir »

Вы попробуйте именно 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 строк а тут такие грабли :(
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

в трекер.
а пользователь точно нормально сможет выбрать из списка в 10000 ? =)
AMD
постоялец
Сообщения: 189
Зарегистрирован: 23.01.2008 21:25:25
Откуда: Кишинев

Сообщение AMD »

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


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

Сообщение debi12345 »

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

Как ни странно - без проблем (мне это тоже стало интересно). Даже с миллионом записей:) К тому же список подстраивается под ручной ввод в текстовой зоне.
Главное - чтобы не тормозило при каждом раскрытии списка.
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

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

так что и смотреть нечего, бага там.
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

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

Сообщение Attid »

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

угу, а до 2000 отрабатывает все нормально =)
Аватара пользователя
Maxx_ir
новенький
Сообщения: 12
Зарегистрирован: 24.02.2008 19:52:00
Откуда: Тольятти
Контактная информация:

Сообщение Maxx_ir »

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
Аватара пользователя
Attid
долгожитель
Сообщения: 2588
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E
Контактная информация:

Сообщение Attid »

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

кто нибуть под линем еще может подтвердить? по поводу того что не все под гтк1 отображается ? например на 5000 записей вижу только на тысячу с конца.
а на 3000 в листе только 20 записей.
Ответить