-
Notifications
You must be signed in to change notification settings - Fork 368
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
better integration between opam and dune for building? #4283
Comments
I experimented with this a while ago (it must be a while now, given that it was with jbuilder!) and in fact that experiment (with an ugly shell script) was what launched the idea of the duniverse tool. The results are indeed very good - I recall hitting a slight snag to do with checksums for the interfaces which boiled down to the fact that I haven't dug the results out, but my recollection was that on a 72 core Azure machine, doing For the opam side, this would be configurable with a declared pattern - i.e. you would tag the package as dune'd and then configure opam to understand that it can assemble the trees differently for packages with this tag. We don't have a spec for this at the moment, though. |
Thinking aloud: one aspect that would require a bit of care is how to read back per-package status report from the result of such a combined build; in particular in the case where some of the packages failed to build. If dune does not provide an easy way to delineate individual status reports, a simple approach (in the failure case) would be to just ask dune to rebuild each subproject in turn, in their existing build directories: for each package this would immediately return a package-specific status report. |
If I understand correctly, you propose here to try to take advantage of intra-package parallelism, which opam cannot exploit currently (meaning that if package A depends on package B, opam will completely build package B before compiling package A, whereas there might be a file A.foo that only depends on B.foo, and that we could build in parallel with B.bar without waiting that it terminates).
This is somewhat orthogonal to the present issue, but indeed, if the overall goal is to improve the speed of From what I remember of my investigation a few months ago:
|
Yes. I think it is relatively common that a package has base modules with few dependencies, and on the outside (of the dependency graph) more user-facing modules with more third-party dependencies (a testing framework, command-line parsing, etc.). So in the common case you can start building the base modules before many of the dependencies are available. (Thanks a lot for the brain dump!) |
The changes file is a very interesting orthogonal suggestion - it's like the |
@dra27 you seem very intent on using flags to customize opam's behavior, while I would more naturally go for detecting from the build rules that the package is just using Dune, and doing the right thing there. (Ideally there would be a syntax to say Could you comment on why you prefer tagging? Here are the points I can come up with, but I don't know that much about opam packaging:
|
The opam client itself shouldn't over-specialise to dune, so there will be no heuristics in the 2.x series about detecting dune commands and overriding its behaviour. Instead, I have an You can find a prototype of this (as a non-opam plugin) at https://github.com/ocamllabs/duniverse if you want to have a play with it now. Note that the duniverse tool will not be released as that tree currently is -- the extra metadata it computes will be folded back into |
Mass-upgrade isn't a big deal. As opam-repository maintainers we do that a weekly basis already ^^ It shouldn't be too hard to detect which projects use dune in a standard way and add a tag. I would personally also be in favour of tagging. It adds the possibility to be backward-compatible and it would be very easy to add to dune's opam file generation. |
I'm interested in approaches that do not change the way we use opam now, just make things faster by taking advantage of the fact that many packages use a build system that nicely support composition. Duniverse sounds like an interesting project, but it is more about enabling new workflows, which is not particularly what I'm after here. That said, @avsm point that the same technical issues would arise in both settings sounds spot on, and I hadn't thought about issues related to vendoring. I suppose that we can have issues if a project has a (vendored) subproject of the same name as another project? Is there a pointer to where these issues are discussed? |
It's quite a complex series of features, involving the interaction between vendored units (private libraries, public libraries, and binaries), and shifting from the opam solver to discriminate based on build rules (via
Until duniverse can reliably assemble full dune monorepos, there will be no meaningful progress on the opam side towards a compositional build workflow (with dune at least). For a successful project or two doing this:
It is no coincidence that both of these projects also have a healthy overlap of maintainers of opam and dune :-) It's taken 1.5 years of work between us to get those working, as it's also involved a lot of porting to dune. But to set realistic expectations, even our core Platform tools do not currently build as a monorepo! But on the other side, we are starting to understand the nature of the scoping needed to support this in dune, but it's not a feature to rush into.
In the short term, you can simply set |
Thanks! One positive thing about this long list of tricky issues is that vendored libraries seem related to how people develop dune-using projects, but are designed to not actually be used once the package is released on opam. This means that focusing on build composition just for faster build at released-package-install-time may be a simpler problem than the general monorepo issue of enabling compositional development. (For example, if we only aim for an installation-time boost and a particular Dune feature makes things tricky, we can always decide to isolate the build of packages using this feature, never including them in composite clusters.) |
Yes, concretely the parallelism plan is fairly "static", if I understand it correctly each package built in parallel gets a fixed number of the total numbers of cores available on the machine. This means that a slow build (or especially a build doing a lot of I/O) can have a huge negative impact. Make can use a jobserver (a shared semaphore using a pipe) to dynamically track available cores, and I think it can use this protocol to collaborate with other build systems as well. There have been discussions about adding jobserver support to dune, which would help solve this problem. This can also help in the case where dune shells out to another build system, for example when using |
@gasche wrote:
I think that's exactly right. One avenue to explore is whether dune-release can create "unvendored" projects for the purposes of opam archives. It still does leave some issues for dune to solve -- for example, ocamlformat and menhir both currently rely on different versions of the @emillon wrote:
It's worse: both opam and dune autodetect the number of jobs, so you get a multiplicative effect on the number of processes running. The jobserver is the only way to fix this systematically across multiple tools. |
A few thoughts about this discussions. First, regarding the job server protocol. The job server protocol would indeed help to improve parallelism when building multiple packages, however it will not perform as well as a single Dune building multiple packages at once. It is easy to see why with an example. Consider a package A that depends on two independent packages B and C. B is small and C is big. When relying on the job server protocol, you have to wait until C finished building before starting the build of A. While with a single Dune instance, you can start building parts of A right from the start. Depending on the set of packages involved, this could range from a small to a big win. Additionally, the job server protocol was designed for recursive make invocations and there are pitfalls when trying to use it as a general way of sharing parallelism between multiple commands. The most important one is the following: if a command that requested tokens crashes without giving back its tokens, the tokens it requested are lost forever and the rest of the builds will have less jobs available. We found this problem while implementing the job server protocol inside Jane Street, and from searching the web we found that the rust community found the same issue. There doesn't seem to be a solution, so opam would need to trust the command it runs to do the right thing and give back their token even in case of a crash. FTR, the way we solved this problem inside Jane Street is by only using the job server in combination with a custom tool similar to GNU parallel but which supports the job server protocol and always gives back its tokens. This was enough for our use case, but it wouldn't be of much help here. Independently of speeding up installation, it would be nice to be able to tag packages that use Dune in the standard way to build. This would allow to make the a few things such as the build instructions or some of the package dependencies be an implementation detail of the system. At the moment, users need to use a specific invocation of Dune to build their package with opam and it's easy to get it wrong. Using the opam file generation feature of dune helps, however some of the details are not completely frozen and have evolved over time. So hiding them and making them true implementation details would allow for more flexibility. |
@jeremiedimino wrote:
Rather than remove the build field, it's easier to (and we often do this) backpatch older revisions using tools like The dune rules are already pretty abstracted away thanks to |
There is definitely value in keeping things simple. |
Indeed, just detecting packages that don't have About parallelism with dune, I concur with @jeremiedimino :
|
Dune is very good at parallelizing work across several (sub)projects, but currently opam does not benefit from this: each package is built (internally in parallel), and package builds are parallelized, but the amount of parallelism can be somewhat disappointing¹.
¹: I haven't seen a precise analysis of the causes, but one reason may be large packages with lots of dependencies that act as parallelism bottlenecks. This is something that @Armael looked at in the context of whole-repo builds, and @kit-ty-kate runs several opam installs in parallel (in independent docker containers) for her whole builds to get better parallelism.
A natural idea would for opam to take advantage of dune's cross-package parallelism in a multi-package install by:
I'm sure that this has already been proposed and discussed. What is the status? Are some people planning to do it, but they haven't had time yet, or maybe there is a blocker when we look at the details?
(One aspect I don't understand very well is if we can use cross-package build "for free" for packages that use Dune, or if we have a problem if they each specify various different options in their "build" rules.)
The text was updated successfully, but these errors were encountered: