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

Use ocaml inotify #4747

Merged
merged 27 commits into from
Jun 23, 2021
Merged

Use ocaml inotify #4747

merged 27 commits into from
Jun 23, 2021

Conversation

aalekseyev
Copy link
Collaborator

@aalekseyev aalekseyev commented Jun 17, 2021

This PR makes dune use inotify library directly instead of relying on an external process (inotifywait).
The reasons for this are:

  • This removes one opaque indirection in reasoning about inotify semantics, putting it under our control. (inotify is already complicated, inotifywait adds its own quirks to the mix).
  • It lets us express interest in a part of the workspace that we're working with. With inotifywait you have to subscribe to the entire workspace, which uses more inotify watches and requires a full workspace scan at startup to establish those watches.

Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
@aalekseyev aalekseyev marked this pull request as ready for review June 21, 2021 09:44
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
@@ -803,6 +865,9 @@ end = struct
t.handler t.config Tick;
match Event.Queue.next t.events with
| Job_completed (job, proc_info) -> Fiber.Fill (job.ivar, proc_info)
| File_watcher_task job ->
job ();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to understand how async_inotify communicates with the scheduler.

IIUC, when async_inotify receive some data from inotify, it sends a (unit -> unit) job to the scheduler via File_watcher_task. This job:

  • processes the data received from inotify and produce a list of Async_inotify.Event.t
  • sends these events one by one to the scheduler via the emit_event callback
  • this callback, provided by dune_file_watcher, packs the event into a list of a single element and adds this list to the event queue

So zooming out, when we receive an inotify event:

  • async_inotify sends a (unit -> unit) callback to the scheduler
  • the scheduler picks it up, execute it and this callback enqueues more things to the event queue
  • the scheduler picks up the newly added events from the queue and process them

It feels like we could simplify this by making async_inotify send a unit -> Event.t list callback to the scheduler instead. WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct.
I agree we should be able to emit a batch of events instead of doing it one by one.
Looking at that...

Copy link
Collaborator Author

@aalekseyev aalekseyev Jun 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed that change. Looks better. I also split pump_events into two parts (based on which thread they run in) and added an .mli (I forgot to copy that in from jane).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks better indeed. Could we go one step further and send a (unit -> Event.t list) to the scheduler rather that send a (unit -> unit) that enqueues more events? That would remove one hoop. We might also be able to move the process_inotify_event to Dune_file_watcher, so that the scheduler never sees the low-level inotify events.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, trying that...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jeremiedimino, I pushed a commit (ba509cb) that makes this change and moves event processing code (including ignored_files) from the scheduler to file watcher. I like the direction this is going. In the current state there's still two separate functions in event queue for:

    val send_file_watcher_task : t -> (unit -> Dune_file_watcher.Event.t list) -> unit
    val send_file_watcher_events : t -> Dune_file_watcher.Event.t list -> unit

but only the former is exposed to the file watcher and we could probably get rid of it, but I thought I'd stop somewhere.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

@ghost
Copy link

ghost commented Jun 22, 2021

Scheduler.Run.Detect_external should be renamed, now that the watcher might be internal. What about Detect or Auto? The command line option takes automatic and manual FWIW, so we could also use Automatic and Manual.

src/dune_engine/fs_memo.ml Outdated Show resolved Hide resolved
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, left a few suggestions.

@snowleopard you should probably read the changes to Fs_memo as well.

Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
…uler thread

Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
@aalekseyev
Copy link
Collaborator Author

Scheduler.Run.Detect_external should be renamed, now that the watcher might be internal. What about Detect or Auto? > The command line option takes automatic and manual FWIW, so we could also use Automatic and Manual.

I like "Automatic". Renaming to that. I've never liked this "manual" name, given that it's impossible to send manual events. I think I'll keep that constructor unrenamed for now because its name at least describes the true behavior.

Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
@snowleopard
Copy link
Collaborator

@snowleopard you should probably read the changes to Fs_memo as well.

@jeremiedimino Thanks for the ping! Looking.

Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Signed-off-by: Arseniy Alekseyev <aalekseyev@janestreet.com>
Copy link
Collaborator

@snowleopard snowleopard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fs_memo changes look good to me but I haven't looked much further, as I guess that got covered by @jeremiedimino's review.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@aalekseyev aalekseyev merged commit 7d5f6cd into ocaml:main Jun 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants