far.Timer: задержка и накопление событий

Здесь обсуждается всё, что касается макросов.
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

far.Timer: задержка и накопление событий

Post by John Doe »

Shmuel wrote: Wed 25 Dec, 2013 13:31 Сигналы Фару о том, что надо вызвать таймер, поступают относительно регулярно, потому что из отдельного потока. Фар в это время может выполнять продолжительную операцию (свою или другого плагина). Вызовы таймера будут задерживаться и могут накапливаться.
Возможно ли в принципе извлечь хотя бы какую-то пользу от накопления вызовов?
Сходу не смог придумать такую задачу.
Может стоит запретить накопление? Чтобы следующий вызов таймера ставился в очередь не ранее, чем начал обрабатываться предыдущий.

С тем, как реализовано сейчас тоже проблем нет. Но если поставить слишком маленький интервал, то можно наблюдать торможение (не исследовал, возможно в итоге память исчерпывается).
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

far.Timer

Post by John Doe »

John Doe wrote: Wed 06 Aug, 2014 14:02Возможно ли в принципе извлечь хотя бы какую-то пользу от накопления вызовов?
Сходу не смог придумать такую задачу.
Зато о вреде легко скажу.
Во-первых, не зная деталей реализации легко ошибиться в использовании этой функции.
И я так делал, и вот свежий пример: http://forum.farmanager.com/viewtopic.p ... 55#p146555

Во-вторых, недавно упоминалось и то, что очередь вызовов не бесконечна, и при определённых условиях может и переполнится.
И даже если не переполнится, но в итоге может накопиться достаточно большое количество (ненужных) вызовов, при обработке которых например интерфейс будет подтормаживать (наблюдал).

Поэтому возвращаюсь к своему предложению:
John Doe wrote: Wed 06 Aug, 2014 14:02Может стоит запретить накопление? Чтобы следующий вызов таймера ставился в очередь не ранее, чем начал обрабатываться предыдущий.
Предполагаю, что можно было бы сделать так: таймер, работающий в отдельном потоке, не просто ставит в очередь пользовательский код, но и контроллирует, что предыдущий элемент очереди выполнен. Если предыдущий не выполнен — то новый не добавляет.

Поправьте, если я где-то ошибаюсь.
User avatar
zg
zero-gravity
Posts: 6207
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 206 times
Contact:

far.Timer

Post by zg »

все задачи с таймерами можно разбить на две группы: где важно количество вызовов и где не важно. текущая реализация работает и там и там. то, что предлагаете вы - работает лишь со второй группой.
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

far.Timer

Post by John Doe »

zg wrote: Fri 20 Oct, 2017 09:57то, что предлагаете вы - работает лишь со второй группой.
Именно, потому что задач первой группы не смог придумать ни одной.
Выше спрашивал, никто тоже не подсказал.

Впрочем, даже с моим предложением можно решить те гипотетические задачи, вычисляя количество пропущенных итераций делением времени, прошедшее с последнего вызова, на период таймера.
User avatar
HaRT
Moderator
Posts: 11458
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 270 times
Been thanked: 417 times

far.Timer

Post by HaRT »

John Doe wrote: Wed 06 Aug, 2014 14:02Может стоит запретить накопление?
Альтернативное решение — объединение одинаковых событий во входной очереди (разумеется, со счётчиком). Разумеется, должны ли события данного типа объединяться, следует решать для каждого типа отдельно. Например, события таймера или автоповторы нажатой клавиши, вероятно, стоило бы объединять.
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

far.Timer

Post by John Doe »

HaRT wrote: Fri 20 Oct, 2017 12:21Альтернативное решение — объединение одинаковых событий во входной очереди
Да, так тоже можно.
Применительно к far.Timer, счётчик событий может быть вторым аргументом функции-хэндлера, либо свойством объекта timer.
HaRT wrote: Fri 20 Oct, 2017 12:21 Разумеется, должны ли события данного типа объединяться, следует решать для каждого типа отдельно.
И это можно, например методом объекта таймер.
Только не соглашусь с формулировкой "Разумеется". Да, это было бы наиболее универсально, и волкам и овцам.
Но нужно ли?

Возможно я не вижу всей картины, но похоже что задачи "первого" типа в реальной практике у нас встречаются редко (надеюсь кто-нибудь хоть один реальный пример приведёт, чтобы было о чём говорить.)
Предлагаемое изменение ещё в изначальной формулировке упростит работу с задачами "второго" типа, при этом (как мне пока кажется) сохранив возможность работы с задачами "первого" типа, хоть и не так удобно.
User avatar
buniak_a_h
Posts: 4565
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 242 times
Been thanked: 674 times
Contact:

Таймер и сборка мусора

Post by buniak_a_h »

В описании таймера написано:
A timer object is garbage-collected only when its lua_State closes, thus it is the application's responsibility to call the Close method when the timer is not needed anymore.
Яндекс-переводчик wrote:Объект timer собирается как мусор только тогда, когда его lua_State закрывается, таким образом, приложение несет ответственность за вызов метода Close, когда таймер больше не нужен.
Я сделал скрипт, создающий таймер "пожизненно" (с загрузки макроса и до прекращения работы ФАРа). В OnTimer опрашиваются логические диски (win.GetLogicalDriveStrings), составляется строка (table.concat) и этот список выводится на панель (far.Text)
У меня создалось впечатление, что через довольно короткое время комп начинает тормозить. Возможно, это - субъективно, т.к. заметно больше всего при работе браузера, а его скорость зависит, в частности, и от сети. В связи с этим у меня несколько вопросов:
  • Может ли длительная непрерывная работа таймера приводить к расходу памяти?
  • Если это так, то есть ли у опытных макрописцев рекомендации, как вызывать сборщик мусора? Возможно, имеет смысл в функции OnTimer закрывать таймер, освобождать (Timer=nil) и создавать снова?
User avatar
HaRT
Moderator
Posts: 11458
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 270 times
Been thanked: 417 times

Таймер и сборка мусора

Post by HaRT »

buniak_a_h wrote: Tue 14 Jan, 2025 23:48 создалось впечатление, что через довольно короткое время комп начинает тормозить
buniak_a_h wrote: Tue 14 Jan, 2025 23:48 Может ли длительная непрерывная работа таймера приводить к расходу памяти?
Так вы бы провели более детальное исследование сначала. Запустите Фар без других плагинов и других макросов и посмотрите хоть в Диспетчере задач, растёт ли объём используемой процессом памяти.
buniak_a_h wrote: Tue 14 Jan, 2025 23:48 как вызывать сборщик мусора?
Безотносительно Луа, вызывать сборщик мусора самостоятельно — это жест отчаяния. По хорошему необходимо просто занулять все переменные (в т.ч. поля таблиц), и особенно типа Замыкание (Closure; например, локально созданные функции), значение которых больше не нужно.
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

Таймер и сборка мусора

Post by John Doe »

Как часто вызывается таймер?
Не может ли быть такого, что в "очереди" накопилось некоторое количество вызовов, которые в какой-то момент начинают разом выполняться?

Можно в обработчике проверить, действительно ли с прошлого вызова прошло достаточно времени.

P.S.
Ну и конечно таймер не имеет смысла, когда фар не в фокусе.
Или же можно управлять им в зависимости от того, когда последний раз приходило клавиатурное или мышиное событие.
Last edited by John Doe on Wed 15 Jan, 2025 00:43, edited 1 time in total.
https://t.me/FarManager — Telegram чат
User avatar
buniak_a_h
Posts: 4565
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 242 times
Been thanked: 674 times
Contact:

Таймер и сборка мусора

Post by buniak_a_h »

HaRT wrote: Wed 15 Jan, 2025 00:25 Безотносительно Луа, вызывать сборщик мусора самостоятельно — это жест отчаяния. По хорошему необходимо просто занулять все переменные (в т.ч. поля таблиц), и особенно типа Замыкание (Closure; например, локально созданные функции), значение которых больше не нужно.
Как вызывать сборщик мусора безотносительно к таймеру - я знаю. Перечисленные Вами мероприятия не всегда приводят к желаемому эффекту просто потому, что сборщик мусора работает "в паузах" (например, когда диалог ждёт клавиатуры). Поэтому иногда (при длительных "расчётных" операциях) приходится вызывать его напрямую (collectgarbage('collect')).
Возможно, я (точнее, Гугл) неправильно перевёл написанное, но понял так, что пока таймер не закрыт (Closed=false), он не даёт сборщику мусора приступить к сборке (ну, или то, что разместил таймер (функция OnTimer) не освобождается и, соответственно, не участвует в сборке мусора.
John Doe wrote: Wed 15 Jan, 2025 00:29 Как часто вызывается таймер?
Часто. По умолчанию - 50 мс
John Doe wrote: Wed 15 Jan, 2025 00:29 Не может ли быть такого, что в "очереди" накопилось некоторое количество вызовов, которые в какой-то момент начинают разом выполняться?
По-моему, не может, т.к. обработчик OnTimer первой же командой запрещает таймер (tmr.Enabled = false), далее делается нечто в обёртке pcall (чтобы даже в случае вылета выполнение OnTimer продолжилось) и только потом "отпускается" таймер (tmr.Enabled = true). Это, вроде, гарантирует не-накопление событий.
John Doe wrote: Wed 15 Jan, 2025 00:29 Или же можно управлять им в зависимости от того, когда последний раз приходило клавиатурное или мышиное событие.
Вообще-то, таймер запускается/перезапускается по событию ConsoleEvent.
User avatar
zg
zero-gravity
Posts: 6207
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 206 times
Contact:

Таймер и сборка мусора

Post by zg »

buniak_a_h wrote: Wed 15 Jan, 2025 01:05Возможно, я (точнее, Гугл) неправильно перевёл написанное, но понял так, что пока таймер не закрыт (Closed=false), он не даёт сборщику мусора приступить к сборке
всё там правильно переведено, не собирается только сам объект и всё что к нему относится. в коде у вас на первый взгляд всё окей, поставил скрипт себе, никаких проблем не наблюдаю.
Last edited by zg on Wed 15 Jan, 2025 01:55, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4565
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 242 times
Been thanked: 674 times
Contact:

Таймер и сборка мусора

Post by buniak_a_h »

zg wrote: Wed 15 Jan, 2025 01:54 никаких проблем не наблюдаю.
Спасибо, Вы подарили мне надежду, что дело не в скрипте.
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

Таймер и сборка мусора

Post by John Doe »

buniak_a_h wrote: Wed 15 Jan, 2025 01:05 Это, вроде, гарантирует не-накопление событий.
Не гарантирует, зависит от реализации таймера (не в вашем коде).
Как убедиться я написал выше.
buniak_a_h wrote: Wed 15 Jan, 2025 06:54 Вообще-то, таймер запускается/перезапускается по событию ConsoleEvent.
Вопрос не в том где он запускается, а в том, предусмотрена ли остановка, если новых событий некоторое время нет.
https://t.me/FarManager — Telegram чат
User avatar
zg
zero-gravity
Posts: 6207
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 206 times
Contact:

Таймер и сборка мусора

Post by zg »

John Doe wrote: Wed 15 Jan, 2025 08:35 Не гарантирует, зависит от реализации таймера (не в вашем коде).
при запрете таймера — события игнорируются.
User avatar
John Doe
Бюрократ
Posts: 14582
Joined: Wed 27 Apr, 2005 20:42
Location: github.com/FarManagerLegacy
Has thanked: 92 times
Been thanked: 514 times
Contact:

Таймер и сборка мусора

Post by John Doe »

zg wrote: Wed 15 Jan, 2025 11:48 при запрете таймера — события игнорируются.
Вопрос в другом: что происходит если какое-то время ACTL_SYNCRO-события не обрабатывается.
  • либо таймер "тупо" пихает новые события в очередь
  • либо "умно" добавляет только если предыдущее уже обработано, а иначе игнорирует.
https://t.me/FarManager — Telegram чат
Post Reply

Return to “Обсуждение макросов”