Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kqueue improvements #24

Closed
4 tasks done
nathany opened this issue Jul 6, 2014 · 7 comments
Closed
4 tasks done

kqueue improvements #24

nathany opened this issue Jul 6, 2014 · 7 comments

Comments

@nathany
Copy link
Contributor

nathany commented Jul 6, 2014

What have I learned from experimenting with kqueue directly (primarily on OS X)? #23

  • fsnotify doesn't watch for Extend, Link or Revoke events (tracked in Support additional event types #519 now).

  • fsnotify has a 100ms timeout on reads, but instead we may be able to just block until kqueue has events available (nil timespec). this could save a little CPU time when idle, see: Increase syscall timeouts to decrease CPU usage? howeyc/fsnotify#58

    • closing the kq (on OS X) results in the read failing with Kevent: interrupted system call, so blocking in a goroutine shouldn't delay shutdown.
  • fsnotify could add multiple file descriptors at once (such as all files in a directory), which may be a little more efficient then adding each one individually.

  • investigated Udata which C programs sometimes use to point to the watched filename, but it's probably not worthwhile from Go (and NetBSD defines Udata differently than the other BSDs).

Other improvements are specific to fsnotify, such as less mutexes #13 and bug fixes #14.

@nathany nathany added this to the kqueue milestone Jul 6, 2014
@nathany
Copy link
Contributor Author

nathany commented Jul 6, 2014

I tried a nil timeout but there is more work involved. Currently syscall.Close(w.kq) is in the same for loop that blocks. Instead it should be called directly by watcher.Close() which will cause the read to abort, after which it can clean up and return.

@nathany
Copy link
Contributor Author

nathany commented Jul 6, 2014

FreeBSD 10.0 behaves a bit differently:

  • Closing the kq descriptor doesn't abort the current read, in fact I still get the next event.
  • Then when setting up the next read, we of course get Kevent: bad file descriptor.

It's not a huge deal if we're calling Close() before shutting down the app, but if not, then the Read goroutine will sit there blocking until it gets another event to send over the channel. And if I do a proper cleanup to DELETE the events, that next event will never come.

@nathany
Copy link
Contributor Author

nathany commented Sep 14, 2014

When registering file descriptors to watch, this could be useful if registering multiple watches at once (such as all the files in a directory):

If an error occurs while processing an element of the changelist and there is enough room in the eventlist, then the event will be placed in the eventlist with EV_ERROR set in flags and the system error in data. Otherwise, -1 will be returned, and errno will be set to indicate the error condition.

Otherwise I don't think I need to check for EV_ERROR. Fsnotify was doing this check, but eventlist was nil, so it should never be the case.

@nathany
Copy link
Contributor Author

nathany commented Sep 14, 2014

When watching a directory with kqueue it reports:

  • a Write when a file is created or deleted
  • a Write and Link when a subdirectory is created or deleted
  • nothing at all when a file is touched (updated)
  • but it does report a Write if modified by an editor that does an atomic save (create and rename)

fsnotify currently adds to this:

  • watches all files in a directory to report updates to specific files.
  • watches for deletes on subdirectories to report the deleted subdirectory, not just a Write+Link
  • when a Write happens on a directory, it scans the directory for any new files/subdirectories and presents them as create events

@nathany
Copy link
Contributor Author

nathany commented Sep 14, 2014

In relation to #16, I was thinking of actually having an event of "something happened in this directory, but we don't know what." Then the scanning and comparing of the files in a directory could be a separate utility function instead of built into readEvents(). It could be used for determining which directory was deleted as well.

But there is still the problem of touching files not reporting any event at all. As well as making the calling code different for kqueue.

@nathany nathany mentioned this issue Sep 15, 2014
@nathany nathany modified the milestones: v1 Internal cleanup, v2 API changes Sep 24, 2014
fjl added a commit to fjl/fsnotify that referenced this issue Mar 4, 2016
As noted in fsnotify#24, reading from the kqueue won't unblock when
it is closed on all platforms. This commit solves the issue by
additionally watching on a pipe which is closed when Watcher
is closed. This makes the read timeout unnessary.
fjl added a commit to fjl/fsnotify that referenced this issue Mar 4, 2016
As noted in fsnotify#24, reading from the kqueue won't unblock when
it is closed on all platforms. This commit solves the issue by
additionally watching on a pipe which is closed when Watcher
is closed. This makes the read timeout unnessary.
fjl added a commit to fjl/fsnotify that referenced this issue Mar 4, 2016
As noted in fsnotify#24, reading from the kqueue won't unblock when
it is closed on all platforms. This commit solves the issue by
additionally watching on a pipe which is closed when Watcher
is closed. This makes the read timeout unnessary.
fjl added a commit to fjl/fsnotify that referenced this issue Mar 4, 2016
As noted in fsnotify#24, reading from the kqueue won't unblock when
it is closed on all platforms. This commit solves the issue by
additionally watching on a pipe which is closed when Watcher
is closed. The read timeout is no longer necessary.
fjl added a commit to fjl/fsnotify that referenced this issue Apr 21, 2016
As noted in fsnotify#24, reading from the kqueue won't unblock when
it is closed on all platforms. This commit solves the issue by
additionally watching on a pipe which is closed when Watcher
is closed. The read timeout is no longer necessary.
pquerna pushed a commit to pquerna/fsnotify that referenced this issue Oct 17, 2016
As noted in fsnotify#24, reading from the kqueue won't unblock when
it is closed on all platforms. This commit solves the issue by
additionally watching on a pipe which is closed when Watcher
is closed. The read timeout is no longer necessary.
@Platin21
Copy link

I always wondered how it deals with atomic writes as i cannot get it to fire again when such a write happens.

@arp242 arp242 removed this from the v2 Internals milestone Jul 29, 2022
@arp242 arp242 removed the research label Jul 29, 2022
@arp242
Copy link
Member

arp242 commented Jan 14, 2023

fsnotify could add multiple file descriptors at once (such as all files in a directory), which may be a little more efficient then adding each one individually.

Add() + Remove() takes 10078ns on my slow VM inside my slow laptop, and I bet most of that is in file operations rather than the syscall:

BenchmarkAddRemove-2      128599             10078 ns/op             848 B/op         13 allocs/op

Not really worth optimizing IMO.

@arp242 arp242 closed this as completed Jan 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants