Вверх ↑
Этот топик читают: Гость
Ответов: 704
Рейтинг: 7
#1: 2019-01-03 21:45:56 ЛС | профиль | цитата
Приветствую! Столкнулся с тем, что таблица строк на 7 строк по 38 колонок каждая ощутимо тормозит главный поток при полной перерисовке через замену строк. И если горизонтальной прокруткой поработать активно, то главный поток совсем вешается на этот период. Так и нужно? Просто каждые 3 секунды данные в таблице полностью обновляются и к таблице имеют доступ через матрицу строк или массив строк другие участки схемы - важно чтоб она функционировала без тормозов. Это слишком большая нагрузка? Компонент для этого не предназначен?

Add(StringTableMT,4905930,532,140)
{
Left=170
Top=5
Width=780
Height=240
Font=[Open Sans,10,0,0,204]
Columns=#1:0|1:1|1:2|1:3|1:4|1:5|1:6|1:7|1:8|1:9|2:10|2:11|2:12|2:13|2:14|2:15|2:16|2:17|2:18|2:19|2:20|2:21|2:22|2:23|2:24|2:25|2:26|2:27|2:28|2:29|2:30|2:31|2:32|2:33|2:34|2:35|2:36|2:37|
ColumnClick=1
MinColWidth=20
MaxColWidth=120
Redaction=0
IconsCheck=[]
MiscIcons=[]
Icons=[]
FileName="online"
SaveColProp=0
SaveWidth=0
Point(Matrix)
Point(Strings)
Point(doReplace)
Point(onDblClick)
Point(doAutoColWidth)
Point(doSave)
}
Add(IndexToChanel,11721130,427,154)
{
Point(Index)
link(onEvent2,4905930:doReplace,[])
}

карма: 0

0
Ответов: 8926
Рейтинг: 823
#2: 2019-01-03 22:41:20 ЛС | профиль | цитата
Neo, компьютер-то глуповат (не то, что мы, программисты), даёшь команду заменить одну строку, а он начинает перерисовывать все десять тысяч
карма: 19

0
Разработчик
Ответов: 26155
Рейтинг: 2127
#3: 2019-01-03 23:03:48 ЛС | профиль | цитата
Neo писал(а):
Компонент для этого не предназначен?

А че схема какая-то куцая, таблица и IndexToChanel в довесок, остальное -- догадайся сам? А данные где, где движуха этих данных, как я могу увидеть тормоза таблицы, если она лысая? А может это не таблица тормозит, а весь остальной кусок схемы, когда системе надо перерисовать таблицу, а схема мочалит данные? Попробуй сгенерировать свою ошибку из десятка компонентов по схожему алгоритму, тогда и глянем, что там конкретно тормозит.
К тому же, я бы крайне не рекомендовал этот тип таблицы, лучше всего использовать MTStrTbl. Она и более функциональна, и более оптимизирована для работы с MT.

--- Добавлено в 2019-01-03 23:09:07

Леонид писал(а):
даёшь команду заменить одну строку, а он начинает перерисовывать все десять тысяч

Так оно и есть, но 10000 это ты хватанул, конечно. А вот всю видимую область -- так это кашей не корми, на любой чих.

Редактировалось 3 раз(а), последний 2019-01-03 23:09:07
карма: 22

0
Ответов: 704
Рейтинг: 7
#4: 2019-01-04 01:19:23 ЛС | профиль | цитата
nesco писал(а):
А может это не таблица тормозит, а весь остальной кусок схемы, когда системе надо перерисовать таблицу, а схема мочалит данные?

Так и оказалось, смоделировал отдельно кусок таблицы. Спасибо за подсказку. Схема большая, где-то кто-то таки мочалит.
карма: 0

0
Ответов: 704
Рейтинг: 7
#5: 2019-01-06 16:52:55 ЛС | профиль | цитата
Всех с наступающим праздником!
Оказалось не в данных дело. Смоделировал схему отдельно. При прокрутке таблицы (захватить и медленно тащить) явно тормозит отсчет событий текстовом поле. Так же все процессы на системном потоке откладываются. Я что-то неправильно применяю? Критические секции поставил для развязки потоков таймера от визуальных элементов.

Add(MainForm,2953706,21,105)
{
Width=1024
link(onCreate,1412819:doEvent1,[(95,125)(95,153)])
}
Add(StringTableMT,4905930,238,147)
{
Left=170
Top=5
Width=780
Height=240
Font=[Open Sans,10,0,0,204]
Columns=#1:0|1:1|1:2|1:3|1:4|1:5|1:6|1:7|1:8|1:9|2:10|2:11|2:12|2:13|2:14|2:15|2:16|2:17|2:18|2:19|2:20|2:21|2:22|2:23|2:24|2:25|2:26|2:27|2:28|2:29|2:30|2:31|2:32|2:33|2:34|2:35|2:36|2:37|
ColumnClick=1
MinColWidth=20
MaxColWidth=120
Redaction=0
IconsCheck=[]
MiscIcons=[]
Icons=[]
FileName="online"
SaveColProp=0
SaveWidth=0
Point(Matrix)
Point(Strings)
Point(doReplace)
Point(onDblClick)
Point(doAutoColWidth)
Point(doSave)
Point(StringTable)
Point(FullTextTab)
}
Add(StrList,9385151,133,98)
{
Strings=#189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|
}
Add(ArrayEnum,13891179,147,147)
{
link(onItem,4905930:doAdd,[])
link(Array,9385151:Array,[])
}
Add(Counter,11129683,175,238)
{
@Color=9371647
Max=999999999
link(onNext,3001738:doEvent1,[])
}
Add(Hub,3001738,224,238)
{
@Color=9371647
OutCount=3
link(onEvent1,10185819:In,[(249,244)(249,230)])
link(onEvent3,14893338:doSafeMode,[])
}
Add(MMTimer,14921899,84,238)
{
@Hint=#23:Основной отсчет времени|
@Color=11206655
Interval=100
Enable=1
link(onTimer,11129683:doNext,[])
}
Add(Timer,15616241,259,315)
{
Interval=150
link(onTimer,2349421:doSafeMode,[])
}
Add(StrCat,6387568,364,315)
{
Str2=" событий"
link(onStrCat,3213322:doText,[])
link(Str1,1428689:Value,[])
}
Add(Memory,1428689,364,252)
{
}
Add(SafeMode,14893338,308,252)
{
Name="time"
WaitMode=1
link(onSafeMode,1428689:doValue,[])
AddHint(-4,40,34,13,Name)
}
Add(SafeMode,2349421,308,315)
{
Name="time"
WaitMode=1
link(onSafeMode,6387568:doStrCat,[])
AddHint(-8,42,34,13,Name)
}
Add(Hub,1412819,105,147)
{
link(onEvent1,13891179:doEnum,[])
link(onEvent2,14921899:doTimer,[(130,160)(130,230)(74,230)(74,244)])
}
Add(Label,3213322,420,315)
{
@Color=9371647
Left=5
Top=10
Width=190
}
Add(LineBreak,7618915,469,224)
{
Caption="Обработка данных"
Primary=[10185819,-126,0]
}

карма: 0

0
Ответов: 8926
Рейтинг: 823
#6: 2019-01-06 17:21:54 ЛС | профиль | цитата
Neo, таскай / не таскай -- везде 10 событий/сек
НичегоНеТормозит.jpg
карма: 19

0
Разработчик
Ответов: 26155
Рейтинг: 2127
#7: 2019-01-06 18:03:23 ЛС | профиль | цитата
Neo писал(а):
Смоделировал схему отдельно

А почему не так?
Схема


Add(MainForm,11618394,245,203)
{
Width=1024
link(onCreate,1412819:doEvent1,[])
}
Add(StringTableMT,4905930,504,217)
{
Left=170
Top=5
Width=780
Height=240
Font=[Open Sans,10,0,0,204]
Columns=#1:0|1:1|1:2|1:3|1:4|1:5|1:6|1:7|1:8|1:9|2:10|2:11|2:12|2:13|2:14|2:15|2:16|2:17|2:18|2:19|2:20|2:21|2:22|2:23|2:24|2:25|2:26|2:27|2:28|2:29|2:30|2:31|2:32|2:33|2:34|2:35|2:36|2:37|
ColumnClick=1
MinColWidth=20
MaxColWidth=120
Redaction=0
IconsCheck=[]
MiscIcons=[]
Icons=[]
FileName="online"
SaveColProp=0
SaveWidth=0
Point(Matrix)
Point(Strings)
Point(doReplace)
Point(onDblClick)
Point(doAutoColWidth)
Point(doSave)
Point(StringTable)
Point(FullTextTab)
}
Add(StrList,9385151,399,168)
{
Strings=#189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|189:2=ON/145;ON/1846;ON/7647;ON/1780;ON/1349;ON/331;ON/1;temp:NA;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF/0;OFF;OFF;OFF;OFF;OFF;OFF;OFF;OFF;ON;OFF;ON;OFF;OFF;OFF;OFF;;temp:NA;temp:NA;ON;ON;ON;ON;ON;ON|
}
Add(ArrayEnum,13891179,413,217)
{
link(onItem,4905930:doAdd,[])
link(Array,9385151:Array,[])
}
Add(Counter,11129683,441,308)
{
@Color=9371647
Max=999999999
link(onNext,3001738:doEvent1,[])
}
Add(Hub,3001738,490,308)
{
@Color=9371647
OutCount=3
link(onEvent1,10185819:In,[(515,314)(515,300)])
link(onEvent3,1428689:doValue,[])
}
Add(StrCat,6387568,546,385)
{
Str2=" событий"
link(onStrCat,3213322:doText,[])
link(Str1,1428689:Value,[])
}
Add(Memory,1428689,546,322)
{
}
Add(Hub,1412819,329,217)
{
link(onEvent1,13891179:doEnum,[])
link(onEvent2,13824852:doStart,[(375,230)(375,314)])
}
Add(Label,3213322,602,385)
{
@Color=9371647
Left=5
Top=10
Width=190
}
Add(LineBreak,4748382,735,294)
{
Caption="Обработка данных"
Primary=[10185819,-126,0]
}
Add(Thread,13824852,385,308)
{
Delay=100
link(onExec,11129683:doNext,[])
link(onSyncExec,6387568:doStrCat,[(431,321)(431,391)])
}


Нафига этот MMTimer нужен? И нафига там вообще SafeMode? Вообще-то работу потоков и надо делать в режиме: асинхронный -- сохраняем данные, синхронный -- даем команду на вывод сохраненных данных.
карма: 22

0
Ответов: 704
Рейтинг: 7
#8: 2019-01-06 21:48:59 ЛС | профиль | цитата
MMTimer как главный таймер для многих операций в моей программке по обработке данных контроллера. Он ведет внутреннее время и показано как оно уходит на "обработка данных" в параллельном потоке. А вывод на форму сделан через сейфмод чтоб избежать ошибки приложения (их таки есть у меня).

nesco, по Вашему примеру объясните, пожалуйста, разве не будет одновременного доступа к данным Memory на запись и на чтение если вдруг отрисовка подвиснет и произойдет следующее событие записи при чтении еще старого по onSyncExec? И разве параллельный поток не теряет свое преимущество параллельности в случае такого частого данных на форму по точке onSyncExec? Он ведь дожидается их обработки визуальными элементами? Таймер у меня читал новое значение реже, чем их отсчитывал MMTimer именно чтоб меньше перерисовывать визуальные элементы.

--- Добавлено в 2019-01-06 22:02:40

Леонид, у меня с предложенной Вами схемой при таскании 8-12 в секунду, и 10 если форму не трогать.

Редактировалось 1 раз(а), последний 2019-01-06 22:02:40
карма: 0

0
Разработчик
Ответов: 26155
Рейтинг: 2127
#9: 2019-01-06 22:32:54 ЛС | профиль | цитата
Neo писал(а):
по Вашему примеру объясните, пожалуйста, разве не будет одновременного доступа к данным Memory на запись и на чтение если вдруг отрисовка подвиснет и произойдет следующее событие записи при чтении еще старого по onSyncExec? И разве параллельный поток не теряет свое преимущество параллельности в случае такого частого данных на форму по точке onSyncExec?

onSyncExec всегда работает в главном потоке, те параллельный поток выставляет флаг на выдачу сообщения и указатель на метод обработки этого события в обработчике главного потока внутренним методом Sender.Synchronize(SyncExec), а сам продолжает выполняться дальше. И ему совершенно безразлично, дойдет это сообщение до главного потока или не дойдет, те параллельный поток не ждет окончания события главного потока. Вот какое сообщение дойдет до главного потока, те текущие данные и будут прочитаны из Memory. И вообще надо исходить из того, что полного распараллеливания априори быть не может, тк все это поточное безобразие работает цепочкой в кольце обработчика ядра системы. А у параллельного потока стоит еще 100 мсек спать, те ни черта не делать, а за это время можно слона съесть.

Редактировалось 4 раз(а), последний 2019-01-06 22:44:38
карма: 22

0
Ответов: 704
Рейтинг: 7
#10: 2019-01-06 22:49:36 ЛС | профиль | цитата
nesco писал(а):
И вообще надо исходить из того, что полного распараллеливания априори быть не может, тк все это поточное безобразие работает цепочкой в кольце обработчика ядра системы.

За то это позволяет не виснуть всей программе в случае работы с сетью, например.

Спасибо за разъяснения. А все флаги обязательны к выполнению в главном потоке, или как и в DeferredEvent - кому повезет, тот и выполнится?

И по поводу вот такого примера, данные уже синхронизированы с главным потоком после MT_String?

Add(MT_String,7923535,462,126)
{
}
Add(DSC_Query,9232878,406,126)
{
SQL="SELECT * FROM tab1 WHERE Sostojanie LIKE '%N%';"
DSManager="parent.parent.mem"
link(onQuery,7923535:doStr,[])
}

карма: 0

0
Разработчик
Ответов: 26155
Рейтинг: 2127
#11: 2019-01-06 23:10:40 ЛС | профиль | цитата
Neo писал(а):
И по поводу вот такого примера, данные уже синхронизированы с главным потоком после MT_String?

Смотря в чем ты это читаешь? MT_String, в данном случае -- буфер, если используется событие onResult, то выдаваться оно будут в том потоке, в котором запущена вся цепь событий. Если же использовать нижнюю точку Result, то прочитать ее можно когда угодно, но будут ли данные актуальны, тут надо уже смотреть весь алгоритм.

Neo писал(а):
А все флаги обязательны к выполнению в главном потоке, или как и в DeferredEvent - кому повезет, тот и выполнится?

DeferredEvent -- это такой же, только короткий оконный обработчик, как и главный. Те оба этих обработчика обрабатываются системой почти одинаково. Те, как система отработает очереди событий для обработчиков, так и будет, похерит она их или не похерит, это уже к ней вопросы. Это вполне может произойти при переполнении очереди событий. Тут все зависит еще и от того, как вызывается обработчик, если послано SendMessage, то вызывающая функция ждет окончания выполнения события, если же как у DeferredEvent -- послано PostMessage, то событие ставится в очередь на обработку, те откладывается, а события цепи выполняются дальше. Естественно, что SendMessage более приоритетен, чем PostMessage, тк невыполнение первого может привести к зависанию приложения, невыполнение же второго просто не приведет к дальнейшим действиям, но управление уже будут передано системе внутри приложения.

Редактировалось 1 раз(а), последний 2019-01-06 23:19:37
карма: 22

0
Ответов: 704
Рейтинг: 7
#12: 2019-01-06 23:56:17 ЛС | профиль | цитата
nesco писал(а):
И вообще надо исходить из того, что полного распараллеливания априори быть не может, тк все это поточное безобразие работает цепочкой в кольце обработчика ядра системы. А у параллельного потока стоит еще 100 мсек спать, те ни черта не делать, а за это время можно слона съесть.

Это дает возможность не использовать мьютекс, читая значение по onSyncExec? События и onExec и onSyncExec отдаются системе на обработку с разным приоритетом и совместного доступа к данным быть не может?
Кажется я избыточно пытаюсь использовать сейфмод в погоне за безотказностью приложения.
карма: 0

0
Разработчик
Ответов: 26155
Рейтинг: 2127
#13: 2019-01-07 00:17:18 ЛС | профиль | цитата
Neo писал(а):
События и onExec и onSyncExec отдаются системе на обработку с разным приоритетом и совместного доступа к данным быть не может?

Тут есть один нюанс -- это использование нескольких потоков для накопления данных, вот тогда надо уже чесать репу, а когда же их читать, по какому onSyncExec, или использовать что-то другое, и не будут ли они лезть одновременно друг с другом к буферу данных на запись.

Редактировалось 1 раз(а), последний 2019-01-07 00:17:51
карма: 22

0
Ответов: 704
Рейтинг: 7
#14: 2019-01-07 00:50:25 ЛС | профиль | цитата
Спасибо, проясняется. Может есть под рукой любой рабочий проект с потоками и их синхронизацией, который можно посмотреть в качестве примера грамотного построения?
карма: 0

0
Разработчик
Ответов: 26155
Рейтинг: 2127
#15: 2019-01-07 01:22:51 ЛС | профиль | цитата
Neo писал(а):
Может есть под рукой любой рабочий проект с потоками и их синхронизацией, который можно посмотреть в качестве примера грамотного построения?

Вот тут http://forum.hiasm.com/topic/67198/2 (в конце) я вроде выкладывал что-то мультипоточное. Посмотри, может пригодится. Эта схема есть полностью мультипоточная, но я ее не выкладывал.

Редактировалось 1 раз(а), последний 2019-01-07 01:24:30
карма: 22

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)