emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Clarification about auto-revert-mode and inotify


From: Dima Kogan
Subject: Re: Clarification about auto-revert-mode and inotify
Date: Fri, 24 Oct 2014 00:02:30 -0700

Hi.

This thread really lost its focus, so let me try to bring it back. My
goals with this thread and patch are what Stefan listed, with some extra
points:

- *very* low resource use when the system is idle.
- prompt updates after a "one time" change FOR LOCAL FILES
- keep Emacs responsive even in case of constant updates or many
  auto-revertable buffers

I'm making an assumption that it would be good to have this in stock
emacs, and not in some odd configuration many of us would never use,
like checking an event-driven flag 100 times every second.

I do agree that making things universally as responsive as a 'tail -f'
would take more work, mainly because each revert can be a heavy
operation. Right now I just want to take care of the low-hanging fruit,
so the above list is good.

Notifications (inotify, etc) are a good way to make this work, so I only
care about the case where notifications are available: local files only.

The patch I attached mostly achieves the goals outlined above, with the
exception of the cost incurred by the per-buffer timers. I'm attaching
another verion of this patch that does not use any timers at all. It
keeps a counter, incrementing during each 'auto-revert-buffers' call.
When an file notification fires, the buffer is updated immediately, and
the current value of the counter is saved. Net time an notification
fires, the immediate update happens ONLY if the counter is different
from the value stored. So there's one global variable (the counter), and
a per-buffer variable for each buffer of interest (the stored counter
value).

If there are specific objections to this patch, performance or
otherwise, please tell me.

Also, it appears that both gfile and inotify notification systems are
misbehaving in emacs right now, so serious tests of this patch probably
wouldn't yield good results yet. Conceptual criticism probably would
have to do for now (this wasn't a problem the last time :) ).

I'm looking at the notification issues now; more on that in a bit.

dima

>From 567d8469dfb143786890c65de58bf2ce887e9ebd Mon Sep 17 00:00:00 2001
From: Dima Kogan <address@hidden>
Date: Fri, 24 Oct 2014 19:44:43 -0700
Subject: [PATCH] auto-revert-mode can now revert immediately in response to a
 change event

If we have file notifications, we want to update the auto-revert buffers
immediately when a notification occurs. Since file updates can happen very
often, we want to skip some revert operations so that we don't spend all our
time reverting the buffer.

We do this by reverting immediately in response to the first in a flurry of
notifications. We suppress subsequent notifications until the next time
`auto-revert-buffers' is called (this happens on a timer with a period set by
`auto-revert-interval').
---
 lisp/autorevert.el | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index f1074e2..7de6ec1 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -531,6 +531,34 @@ will use an up-to-date value of `auto-revert-interval'"
       ;; Fallback to file checks.
       (set (make-local-variable 'auto-revert-use-notify) nil))))
 
+
+
+;; If we have file notifications, we want to update the auto-revert buffers
+;; immediately when a notification occurs. Since file updates can happen very
+;; often, we want to skip some revert operations so that we don't spend all our
+;; time reverting the buffer.
+;;
+;; We do this by reverting immediately in response to the first in a flurry of
+;; notifications. We suppress subsequent notifications until the next time
+;; `auto-revert-buffers' is called (this happens on a timer with a period set 
by
+;; `auto-revert-interval').
+(defvar auto-revert-buffers-counter 1
+  "Incremented each time `auto-revert-buffers' is called")
+(defvar auto-revert-buffers-counter-lockedout 0
+  "Buffer-local value to indicate whether we should immediately
+update the buffer on a notification event or not. If
+
+  (= auto-revert-buffers-counter-lockedout
+     auto-revert-buffers-counter)
+
+then the updates are locked out, and we wait until the next call
+of `auto-revert-buffers' to revert the buffer. If no lockout is
+present, then we revert immediately and set the lockout, so that
+no more reverts are possible until the next call of
+`auto-revert-buffers'")
+(make-variable-buffer-local 'auto-revert-buffers-counter-lockedout)
+
+
 (defun auto-revert-notify-handler (event)
   "Handle an EVENT returned from file notification."
   (with-demoted-errors
@@ -566,6 +594,14 @@ will use an up-to-date value of `auto-revert-interval'"
                                 (file-name-nondirectory buffer-file-name)))))
                 ;; Mark buffer modified.
                 (setq auto-revert-notify-modified-p t)
+
+                ;; Revert the buffer now if we're not locked out
+                (when (/= auto-revert-buffers-counter-lockedout
+                          auto-revert-buffers-counter)
+                  (auto-revert-handler)
+                  (setq auto-revert-buffers-counter-lockedout
+                        auto-revert-buffers-counter))
+
                 ;; No need to check other buffers.
                 (cl-return)))))))))
 
@@ -686,6 +722,10 @@ are checked first the next time this function is called.
 This function is also responsible for removing buffers no longer in
 Auto-Revert mode from `auto-revert-buffer-list', and for canceling
 the timer when no buffers need to be checked."
+
+  (setq auto-revert-buffers-counter
+        (1+ auto-revert-buffers-counter))
+
   (save-match-data
     (let ((bufs (if global-auto-revert-mode
                    (buffer-list)
-- 
2.0.0


reply via email to

[Prev in Thread] Current Thread [Next in Thread]