C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Индикация процесса (ProgressBar), почему так сильно тормозит?
Young Coder
Отправлено: 31.07.2003, 17:45


Дежурный стрелочник

Группа: Участник
Сообщений: 34



Реально, есть цикл... не важно что в нем...
и если просто запустить его, то он выполнятется за 10 секунд.
Но логично, что процессы которые длятся более 3 секунд должны быть показаны (индикация) пользователю... чтобы он не подумал что прога висит... но стоит шлепнуть ProgressBar и показывать на нем чего да как...  — прога выполняет скрипт примерно в два, три раза долше.
Понятно, что это из-за визуализации... НО, черт, как это обойти?
Admin
Отправлено: 31.07.2003, 22:33


Владимир

Группа: Администратор
Сообщений: 1190



Конечно визуализация происходит медленно, но вряд-ли
отбражение ProgressBar увеличивает время в 3 раза
(с 10 до 30 секунд), наверное дело в чем то еще ?

Возможно:

1/ Идет сложный расчет, текущего значения ProgressBar,
на это тратится процессорное время.

2/ А вы случайно в этом цикле не выводите-ли что либо еще
на экран ? (не только ProgressBar) и прыгает с вывода
ProgressBar на вывод-перерисовку чего-то другого.

3/ И не запихнут-ли у вас цикл в отдельный поток ?
Если зипихнут, то время будет тратиться на переключение
между потоками.

Георгий
Отправлено: 31.07.2003, 23:39


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Young Coder
со временами ты конечто загнул!
Хотя кто тебя знает — вдруг ты на 386DX-40 + 8Mb RAM + Trident 512kb сидишь?
Индикатор действительно рисуется медленно... А ты индикатор двигай шагами — например по 20% — пользователю разницы между 1% и 20% нет ни какой, а у тебя в 20 раз меньше затрат времени на перерисовку!

Admin
с № 1 могу согласиться :-))
с № 2 может Young Coder согласиться :-]]
с № 3 не согласен: ;-]]
3.1 если цикл с TProgressBar`ом в потоке, то время действительно будет тратиться, но не на переключение задач, а на синхронизацию с основным потоком (TProgressBar — VCL обьект и не очень должен любить работу не из основного потока).могу ошибаться — так что если не прав поправьте
3.2 переключение задач... Ах — моя любимая тема...
с того момента как Intel реализовала поддержку многозадачности на аппаратном уровне, затраты времени свелись практически к нулю. Зубков говорит, что у P5 на это уходит около 85 тактов (386 — ~310). Да и MS Windows не очень часть задачи переключает — кажется каждые 30ms (переключение по таймеру при равных приоритетах и отсутствии активных задач с большим приоритетом). => 85 округляем до 100 и умножаем на число переключений в секунду 1/0,03 = 3333 тактов на переключение задач => для P5-100MHz это 0,033ms т.е. 999,96667 ms из секунды, что соответствует 99,996667% машинного времени P5, остаётся для других задач.
так что потоки можно сотнями штамповать! Но надо быть осторожным — у мелкомягких свой взгляд на многозадачность и потоки одной задачи кажется вообще не конкурируют между собой — кто первым занял процессор, тот и будет его использовать, а остальные потоки ждут...
Young Coder
Отправлено: 01.08.2003, 10:10


Дежурный стрелочник

Группа: Участник
Сообщений: 34



Спасибо за ответы, а как вы смотрите, если в качестве альтернативы просто выводить _типа_форму_ с тикающими часиками?
- не надо просчитывать прогресс...
- юзер видит что что-то делается...

Как вы считаете?
Admin
Отправлено: 01.08.2003, 10:45


Владимир

Группа: Администратор
Сообщений: 1190



Георгий

QUOTE

3.1 если цикл с TProgressBar`ом в потоке, то время действительно будет тратиться, но не на переключение задач, а на синхронизацию с основным потоком (TProgressBar — VCL обьект и не очень должен любить работу не из основного потока).


Да, именно это и имел ввиду, особенно как реализованы потоки
в C++Builder (точнее синхронизация с VCL объектами) через
Synhronize().


QUOTE

так что потоки можно сотнями штамповать!


Кхм...

"Также, при создании потоков следует учитывать, что слежение за слишком многими потоками потребляет процессорное время; рекомендованный предел — 16 активных потоков на процесс на системах с одним процессором."

(Из перевода Help-а к C++Builder или еще не помню откуда)

Отредактировано Admin — 01/08/2003, 11:48
Георгий
Отправлено: 01.08.2003, 11:06


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



если у тебя пользователи пассивные smile.gif то так и делай, а если у тебя идёт очень важный процесс, то лучше прогрессбар — так пользователям спокойнее

Admin
да это из help`a к BCB, но посмотри сколько потоков сам Microsoft делает — у него в среднем 30 на одну задачу...
А число активных — ну с таким телом:
for (int i=0;i<1000000;i++);
в 98-м больше 4-х одновременно не работают
а в XP больше 2-х одновременно не работают
вот и получается то, о чём я в последнем предложении предыдущего постинга говорил

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

потока, с полем типа volatile int* ptr
и таким кодом:
for (int i=*ptr;i;i--)
*ptr=i
в главной форме пишем:
const size_v=15;
votalile int values[size_v];
TEdit*   Edits[size_v];
обработчик таймера:
for (i=0;i<size_v;i++) Edits[i]->Text=values[i];
обработчик кнопки:
Timer->Enabled=false;
for (i=0;i<size_v;i++)values[i]=1000000;
Edits[0]=Edit1;
Edits[1]=Edit2;
...
Edits[14]=Edit15;
Timer->Enabled=true;
for (i=0;i<size_v;i++)
{
TMyThread* t=new TMyThread(true);
t->ptr=&values[i];
t->FreeOnTerminate=true;
};

и результат работы этой программы наглядно покажет, как время разделяется между процессами одной задачи. У меня, как я уже говорил, больше 4-х потоков одновременно не выполнялось (это по значениям Edit видно)

А в том случае, когда потоки находятся в режиме ожидания — времени на их обслуживание вообще не должно тратиться.

Так что формально я прав — потоков можно делать сколько угодно, но фактически не прав — одновременно работать больше n (где n определяется экспериментально) не будут.

Отредактировано Георгий — 01/08/2003, 12:43
Admin
Отправлено: 01.08.2003, 17:39


Владимир

Группа: Администратор
Сообщений: 1190



QUOTE

Admin
да это из help`a к BCB, но посмотри сколько потоков сам Microsoft делает — у него в среднем 30 на одну задачу


Так это большая разница !
Наверняка Microsoft организует работу потоков через
функции Win32Api (а то и ниже)
CreateThread() и т.д., а не через TThread

Тоже самое можно реализовать и в C++Builder -
создаете и полностью работаете с потоками через
функции Win32API, только не обращайтесь к VCL объектам !

(у меня знакомый создает в отдельном потоке окно/окна
через WinApi и работает с ним в отдельном потоке/потоках ) -
разумеется работает быстрее и правильнее.
Георгий
Отправлено: 02.08.2003, 11:15


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Admin
что бы у читающих не сложилось впечатление, что TThread, использовать нельзя или не имеет смысла:

TThread скорее всего банальная обьектная обёртка для того же CreateThread, так что создание потоков через TThread и CreateThread — эквивалентные варианты (в том числе в плане ограничений)

VCL — да это у Borland получился ёжик — вроде работает, но трогать нельзя — уколет. Поэтому, как я считаю, потоки и оконные формы реализованные в VCL несовместимы, но ни что не мешает в пределах потока использовать другие VCL обьекты, в описании которых явно не указано, что они не любят много поточность.

Так что использовать TThread можно наравне с чистым Win32API.
Admin
Отправлено: 02.08.2003, 14:50


Владимир

Группа: Администратор
Сообщений: 1190



Мое мнение, что в 99% программ можно (и нужно) обойтись совсем
без использования потоков.
(Если конечно не пишем какую-либо игрушку или текстовый
процессор типа Word, например чтоб в отдельном потоке
проверять орфографию и т.д.)

Из оставшегося 1% конечно правильней работать через
CreateThread(), а через TThread — искать приключений, глюков и тормозов, и если сложится такое впечатление, то и хорошо,
пусть изучают Win32API — очень хорошо работа с потоками
описана в книге:

"Windows 98 Руководство разработчика" в 2-х томах
Бен Эззель, Джим Блейни (Изд. "BHV")
там и диск с примерами есть (он есть в закрытом форуме)

user posted image

Использовать-же TThread конечно можно, но очень редко
когда реально это понадобиться.

Другими словами — если программа простая — потоки не нужны,
или можно использовать TThread,
если сложная — лучше использовать CreateThread(),
а при использовании TThread в сложной программе
будет очень сложно отслеживать все взаимодействие
с VCL объектами.

Георгий
Отправлено: 03.08.2003, 17:44


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Одобрямс!

Но только почему такая не любовь к TThread? Я никаких отличий от CreateThread не заметил.
Admin
Отправлено: 03.08.2003, 21:56


Владимир

Группа: Администратор
Сообщений: 1190



Нет, нелюбовь тут не причем, а чисто практически — скорость !
Как я уже говорил, мой знакомый написал работу с потоками
в программе через CreateThread(),
и ради интереса такой-же через TThread — разница по скорости
оказалась большая.

И кстати, также испытали компоненты — таблица в памяти -
RxMemoryData из библиотеки RXLib
и компонент kbmMEMTABLE — так вот скорость работы kbmMEMTABLE
оказалась на порядок выше, конечно, где скорость важна,
используем теперь его.

Так и с потоками. Если работать в программе типа Word,
то разницы в скорости можно и не заметить, (проверяется себе
орфография в отдельном потоке и все), а вот если
есть большая база данных, идут сложные вычисления,
конечно скорость и время становятся важными величинами.
Георгий
Отправлено: 05.08.2003, 13:44


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Владимир
Признаю себя побеждённым — CreateThread в натуре работает быстрее, чем TThread

статистика с прилагающейся программы (все значения в tick):
CreateThread:
RunTime=2325671
LiveTime=2888392

TThread:
RunTime=5232580
LiveTime=5833822

Скоро этот алгоритм перенесу на QNX4.25 и посмотрю как там с многопоточностью...

User Attached Image Скачать файл
TestThreads.rar



Вернуться в Вопросы программирования в C++Builder