-
Notifications
You must be signed in to change notification settings - Fork 52
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
New WatchService
based on Java 7's WatchService
#47
Conversation
WatchService
based on Java 7's WatchService
WatchService
based on Java 7's WatchService
I've been doing some benchmarking, and the results with Here are the results of the benchmarks: https://travis-ci.org/Duhemm/io/builds/246090849
|
199740c
to
d2a6570
Compare
The goal of this is to add an abstraction layer so that we can define new kinds of `WatchService`s. This way, we can use the default `WatchService` provided by the JDK on certain platform (e.g. Windows), and revert back to the `PollingWatchService` that existed before, on machine where there's no native support for monitoring the file system (e.g. macOS). This commit includes an adapter for the `WatchService` from Java NIO to our new interface, and a port of the existing `PollingWatchService`.
d2a6570
to
3f7488b
Compare
WatchService
based on Java 7's WatchService
WatchService
based on Java 7's WatchService
Benchmarking results on Windows: https://ci.appveyor.com/project/Duhemm/io/build/12 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comments about duration, but overall looks good. Could you also prepare a corresponding PR to sbt/sbt plz?
import scala.collection.mutable | ||
|
||
/** A `WatchService` that polls the filesystem every `delayMs` milliseconds. */ | ||
class PollingWatchService(delayMs: Long) extends WatchService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use Duration.
* @param timeoutMs Maximum time to wait, in milliseconds. | ||
* @return The next `WatchKey` that received an event. | ||
*/ | ||
def poll(timeoutMs: Long): WatchKey |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use Duration.
@eed3si9n Done! Corresponding sbt/sbt PR: sbt/sbt#3295 |
dbuild has checked the following projects against Scala 2.12:
❌ The result is: FAILED |
|
||
import scala.concurrent.duration._ | ||
|
||
abstract class SourceModificationWatchSpec(getService: => WatchService, pollDelay: FiniteDuration, maxWait: FiniteDuration) extends FlatSpec with Matchers { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this tested on all three major platforms? Because the semantics are very different and there are OS limitations to fidelity of changes (e.g. the Linux kernel only records FS accuracy to second precision on most filesystems)
if (terminationCondition) { | ||
(false, state) | ||
} else { | ||
Thread.sleep(delay.toMillis) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouch
if (filteredCreated.nonEmpty || filteredDeleted.nonEmpty || filteredModified.nonEmpty) { | ||
(true, newState.withCount(newState.count + 1)) | ||
} else { | ||
Thread.sleep(delay.toMillis) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouch again
I'm a little confused about the implementation of this. It doesn't seem to use NIO as much as it could, and therefore will be very limited in its performance gains. e.g. I couldn't find any use of the walk pattern https://docs.oracle.com/javase/tutorial/essential/io/walk.html which is orders of magnitude faster on Windows. Is this only tested in travis? You really need to test in in appveyor to see Windows behaviour and even OS X / Linux kernels make a big difference when it comes to IO. We cracked almost all of these problems in ensime already with https://github.com/ensime/java7-file-watcher and (GPLv3 but we'd be willing to talk about it) https://github.com/ensime/ensime-server/blob/2.0/core/src/main/scala/org/ensime/indexer/FileWatchers.scala https://github.com/ensime/ensime-server/blob/2.0/core/src/main/scala/org/ensime/filewatcher/FileWatchService.scala (it's not pretty, I'd rather use an fs2 |
BTW, when we swapped to NIO in ensime (and even some of my sbt hacks to use nio for jar packing) I was seeing x1000 improvements on large projects in windows. Actually sometimes it was the difference between "working" and "using all CPUs and not working at all, not even nearly". I believe this PR only unlocks a very small percentage of the potential gains. |
The goal was to use This PR also puts everything in place to let users write new
This has been tested locally and on Travis with MacOS and Linux, and on AppVeyor on Windows. |
We've had all these discussions before in ensime (especially re OS X), I really wish you'd reached out because it would have saved you a tonne of time doing your research. "has been tested" != "is tested" (but == "has rotted"). Can sbt get an appveyor subscription and include this as part of CI? |
The goal of this is to add an abstraction layer so that we can define
new kinds of
WatchService
s. This way, we can use the defaultWatchService
provided by the JDK on certain platform (e.g. Windows),and revert back to the
PollingWatchService
that existed before, onmachine where there's no native support for monitoring the file system
(e.g. macOS).
This commit includes an adapter for the
WatchService
from Java NIO toour new interface, and a port of the existing
PollingWatchService
.This commit shows how it integrates within sbt/sbt: Duhemm/sbt@f5060f2