mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-08 23:40:24 -08:00
Call igc--on-idle multiple times per idle period
This makes the exact value of igc--idle-delay less import because igc--on-idle is now called after igc--idle-delay then after igc--idle-delay * 2, then igc--idle-delay * 4, and so on. * lisp/emacs-lisp/igc.el (igc--on-idle): Start a second timer until igc--idle-repetitions is reached. (igc--idle-delay): Use 1.0 as default. (igc--idle-repetitions): New. (igc--current-idle-time): New helper. (igc--predict-idle-time): Use it.
This commit is contained in:
parent
2e76caa312
commit
d37f079bad
1 changed files with 39 additions and 8 deletions
|
|
@ -394,33 +394,64 @@ Used in calls to `format-time-string'.")
|
|||
(defvar igc--idle-timer nil
|
||||
"Idle timer to trigger oppurtunistic GC.")
|
||||
|
||||
(defvar igc--idle-delay 2.0
|
||||
(defvar igc--idle-delay 1.0
|
||||
"Time, in seconds, to wait for `igc--idle-timer'.")
|
||||
|
||||
(defvar igc--idle-repetitions 6
|
||||
"How many times to wait.")
|
||||
|
||||
(defvar igc--step-interval 0.01
|
||||
"Time, in seconds, MPS is allowed to use for one step.")
|
||||
|
||||
;;;###autoload
|
||||
(defun igc-start-idle-timer ()
|
||||
"Start a timer to do GC work while Emacs is idle."
|
||||
(cl-assert (< igc--step-interval igc--idle-delay))
|
||||
(when igc--idle-timer
|
||||
(cancel-timer igc--idle-timer))
|
||||
(setq igc--idle-timer
|
||||
(run-with-idle-timer igc--idle-delay t #'igc--on-idle)))
|
||||
(run-with-idle-timer igc--idle-delay t
|
||||
#'igc--on-idle (vector nil) 0)))
|
||||
|
||||
(defun igc--current-idle-time ()
|
||||
(let ((idle-time (current-idle-time)))
|
||||
(if idle-time (float-time idle-time) 0)))
|
||||
|
||||
(defun igc--predict-idle-time ()
|
||||
(* igc--idle-delay 0.66))
|
||||
(* (igc--current-idle-time) 0.80))
|
||||
|
||||
(defun igc--on-idle ()
|
||||
;; The igc-idle-timer works a bit like the blink-cursor-timer. It can
|
||||
;; call 'gc--on-idle' multiple times per idle cycle either until some GC
|
||||
;; work is done or until `igc--idle-repetitions' is reached. We do this
|
||||
;; because our idle time prediction primarily depends on the
|
||||
;; `current-idle-time', i.e. our predicted idle time gets larger the
|
||||
;; larger `current-idle-time' gets.
|
||||
;;
|
||||
;; We try to recover from too optimistic predictions quicky, by calling
|
||||
;; `igc--arena-step' with a relatively short `igc--step-interval' and
|
||||
;; use `accept-process-output' to check if some output arrived, before
|
||||
;; calling 'igc--arena-step' again.
|
||||
|
||||
(defun igc--on-idle (state repetition)
|
||||
(let ((timer2 (aref state 0)))
|
||||
(when timer2
|
||||
(cancel-timer timer2)))
|
||||
(let* ((available-time (igc--predict-idle-time))
|
||||
(interval igc--step-interval)
|
||||
(multiplier (floor (/ available-time interval))))
|
||||
(named-let step ((n multiplier))
|
||||
(let* ((work-to-do (igc--arena-step interval n)))
|
||||
(when (and work-to-do
|
||||
(> n 0)
|
||||
(not (accept-process-output nil 0)))
|
||||
(step (1- n)))))))
|
||||
(cond ((and work-to-do
|
||||
(> n 0)
|
||||
(not (accept-process-output nil 0)))
|
||||
(step (1- n)))
|
||||
((and (not work-to-do)
|
||||
(= n multiplier)
|
||||
(< repetition igc--idle-repetitions))
|
||||
(aset state 0 (run-with-idle-timer
|
||||
(+ (igc--current-idle-time)
|
||||
(* igc--idle-delay (ash 1 repetition)))
|
||||
nil #'igc--on-idle state (1+ repetition)))))))))
|
||||
|
||||
(provide 'igc)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue