Оптимизация загрузки текстового файла

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Оптимизация загрузки текстового файла

Сообщение hCORe » 20.11.2004 (Сб) 18:23

Загрузка и обработка текстового файла (разделитель - запятые) с добавлением записей с иконками в TreeView происходит подозрительно медленно. На моей машине тест показал 549 мс (в exe файле). В идеале вся операция должна идти лишь 1/10 этого времени. Программа очень критична к производительности (по крайней мере, во время загрузки.) Код теста прилагается. Кто что посоветует?
Вложения
TreeViewTest.zip
TreeViewTest Application
(79.06 Кб) Скачиваний: 26
Моду создают модоки, а распространяют модозвоны.

xolod
Гуру
Гуру
 
Сообщения: 1162
Зарегистрирован: 15.01.2004 (Чт) 0:42
Откуда: Moscow

Сообщение xolod » 20.11.2004 (Сб) 22:53

1) Для начала - отключи на время загрузки перерисовку treeview (SendMessage TreeView.hwnd, WM_SETREDRAW, 0, 0), после загрузки ессесно включи
2) Убери все DoEvents, если таковые имеются
3) Split (впрочем как и vb'шные функции, ОЧень медленная, так что..)
4) Не пиши лог :lol:

Constant ERROR_SUCCESS deprecated. I'm so happy.
Программирование и дизайн – http://www.macrointellect.ru

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 21.11.2004 (Вс) 1:52

xolod, это не прокатит - басиковое дерево игнорирует посланные ему WM_SETREDRAW. Я в свое время столкнулся с этим, и кажется, так и не решил. Можно попробовать посылать ему это сообщение дважды подряд - тогда иногда срабатывает. По крайней мере, иногда...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.11.2004 (Вс) 11:14

А если TreeView сделать невидимым? Во всяком случае это работает на ListBox и ListView.
Lasciate ogni speranza, voi ch'entrate.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 21.11.2004 (Вс) 11:22

Если невидимым, то так:

...
DoEvents
Me.tvw_Tree.Visible = False
DoEvents
...
Иначе может не сработать.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.11.2004 (Вс) 11:32

Во-первых, измени ReDim Preserve.
Советую примерно такой алгоритм:
Код: Выделить всё
Dim arr(), C As Long, N As Long
C = 0
N = 0
ReDim arr(0)
Do
  ...
  If ... Then
    C = C + 1
    If C > N Then ReDim
      N = N + 100
      ReDim Preserve arr(0 To N)
    End If
    arr(C) = ...
  End If
Loop
ReDim Preserve arr(0 To C)

ReDim Preserve не самая быстрая операция и количество ее выполнений лучше уменьшить.

Правда я это сделал и особого быстродействия не заметил, но все же загрузка идет немного быстрее.

Все строки, которые используются, замени на константы. Т.е. не "", а vbNullString, не ";", а vbStrSemicolon (а в модуле Const vbStrSemicolon As String = ";") и т.п. Насчет скорости не уверен, а память сэкономишь.

Что-то надо делать с DrawSkinIcon. Советую все иконки загрузить в массив StdPictures и присваивать значки из массива. Еще лучше заменить на API.

Ну и я бы пересмотрел способ заполнения дерева. Каждый раз искать в коллекции ключевой элемент, к которому добавляются остальные элементы... Лучше объяви массив Node и храни их в памяти все то время, пока идет заполнение списка.
Lasciate ogni speranza, voi ch'entrate.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.11.2004 (Вс) 11:33

Ennor, помоему когда окно делается видимым/невидимым, оно перерисовывается само, без принудительного рефреша.
Lasciate ogni speranza, voi ch'entrate.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 21.11.2004 (Вс) 11:36

alibek писал(а):Ennor, помоему когда окно делается видимым/невидимым, оно перерисовывается само, без принудительного рефреша.

Ну да, как правило. Во всяком случае, InvalidateRect() для него всяко вызывается. Я просто не понял - ты о чем именно?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 21.11.2004 (Вс) 11:44

Ennor, а я видимо не понял, зачем DoEvents :)
Без него у меня все работало.
Lasciate ogni speranza, voi ch'entrate.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 21.11.2004 (Вс) 11:47

Ясно :) А вот у меня не работало, причем гораздо более важным оказывался первый DoEvents, нежели второй. Видимо, тачка слишком слабая...

Ruslan Demidow
Мужчина!
Мужчина!
Аватара пользователя
 
Сообщения: 987
Зарегистрирован: 25.03.2004 (Чт) 13:39
Откуда: N.Novgorod

Сообщение Ruslan Demidow » 21.11.2004 (Вс) 12:16

Ennor писал(а):xolod, это не прокатит - басиковое дерево игнорирует посланные ему WM_SETREDRAW. Я в свое время столкнулся с этим, и кажется, так и не решил. Можно попробовать посылать ему это сообщение дважды подряд - тогда иногда срабатывает. По крайней мере, иногда...

Может быть и неверно, но Эпллман писал, что WM_SETREDRAW контролы принимают к сведению, если для работы с контролами использовать тоже сообщения (т.е. API).
Любое родное (бейсиковое) действие типа AddItem, RemoveItem, NоdeAdd объявляет регион недействительным и принудительно заставляет его перерисовываться. Поэтому и не срабатывает WM_SETREDRAW.
Это Ж-ж-ж-ж неспроста (с) Винни-Пух

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 21.11.2004 (Вс) 12:49

Не скажи: RTB прекрасно блочит перерисовку, даже если с ним после этого работать на уровне .SelForeColor . Это только дерево такое... деревянное.

Ruslan Demidow
Мужчина!
Мужчина!
Аватара пользователя
 
Сообщения: 987
Зарегистрирован: 25.03.2004 (Чт) 13:39
Откуда: N.Novgorod

Сообщение Ruslan Demidow » 21.11.2004 (Вс) 14:11

Ennor писал(а):Не скажи: RTB прекрасно блочит перерисовку, даже если с ним после этого работать на уровне .SelForeColor . Это только дерево такое... деревянное.
Согласен. Но списки, комбобоксы и т.п. при использовании бейсиковских методов ведут себя именно так как я сказал.
Это Ж-ж-ж-ж неспроста (с) Винни-Пух

xolod
Гуру
Гуру
 
Сообщения: 1162
Зарегистрирован: 15.01.2004 (Чт) 0:42
Откуда: Moscow

Сообщение xolod » 21.11.2004 (Вс) 16:45

Так, проверил, деревяшка действительно не блочиться :?

Еще варианты:

1) Заюзать (блочит все окно нафик)
Код: Выделить всё
Declare Function LockWindowUpdate Lib "user32" Alias "LockWindowUpdate" (ByVal hwndLock As Long) As Long


2) Использовать treeview, что на vbAccelerator лежит (его правда немного поправить надо), работает быстрее.

Constant ERROR_SUCCESS deprecated. I'm so happy.
Программирование и дизайн – http://www.macrointellect.ru

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 21.11.2004 (Вс) 17:57

Почитал про LockWindowUpdate() - суровая штука, ничего не скажешь. Проверь, действительно, вдруг поможет...

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 21.11.2004 (Вс) 18:37

Помогло, но немного... Теперь грузит данные не 549, а 312 мс. Но надо-то 50 мс :x
Вот, выкладываю. И повторяю: DoEvents убрать, к сожалению, нельзя. И все тут :evil:
Вложения
TreeViewTest2.zip
TreeViewTest Application ver. 2
(78.8 Кб) Скачиваний: 26
Моду создают модоки, а распространяют модозвоны.

Юстас
Бывалый
Бывалый
 
Сообщения: 200
Зарегистрирован: 24.10.2003 (Пт) 5:05

Сообщение Юстас » 23.11.2004 (Вт) 18:47

For lngL = 0 To UBound(arrLines) - 1 - зачем раз за разом вычислять размерность массива ?
j = UBound(arrLines) - 1
For lngL = 0 To j
================================================
- зачем раз за разом в цикле проверять длину переменной, которая не меняется?
If Len(Trim$(Ln)) <> 0 Then

End If

Вынеси этот If...End If за цикл

================================================
Dim sc As Long, sx As Long - зачем опять же в цикле раз за разом определять переменные?
Тем более если не используешь их ?

================================================
If Mid$(CDir, Len(CDir), 1) <> "\" Then CDir = CDir & "\" - и ещё раз зачем в цикле раз за разом вставлять бэкслэш в строку, которая не меняется?

А вообще для VB задача непосильная, имхо. 50 мс нереально для этого алгоритма. Ради эксперимента смоделировал чтобы ни одна иконка не была добавлена в TreeView, и результат получился 47 мс. Это просто пустые операции по подготовке к загрузке рисунка.
За оставшиеся 3 мс ни в какой TreeView ты ничем не загрузишь иконки. Мне так кажется. :) И никакой LockWindowUpdate не поможет.

marvan
Бывалый
Бывалый
 
Сообщения: 269
Зарегистрирован: 22.06.2004 (Вт) 13:26
Откуда: Москва

Сообщение marvan » 24.11.2004 (Ср) 10:50

основное время (381ms относительно общего 516ms) съедает эта строка
iml2.ListImages.Add , "__key@" & CStr(lngL), LoadPicture(ml2)
Так что treeview тут не при чём.
А я ведь в своё время рекомендовал грузить графику из ресурсов.


Вернуться в Visual Basic 1–6

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

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

    TopList  
cron