You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Your IDE's "*jump-to-definition*" in Mill actually brings you to the implementation of a task, rather
24
+
than an `sbt` `taskKey` declaration.
25
+
Customizing things is as simple as writing or overriding ``def``s.
26
+
The net effect is that despite both tools' build files being written in Scala,
26
27
Mill's build files are much easier to understand and maintain.
27
28
28
-
This page compares using Mill to `sbt`, using the https://github.com/gatling/gatling[Gatling Load Testing Framework]
29
-
codebase as the example. Gatling is a medium sized codebase, 40,000 lines of Scala split over 21
30
-
subprojects. By porting it to Mill, this case study should give you an idea of how Mill compares
31
-
to `sbt` in more realistic, real-world projects.
29
+
This page compares using Mill to `sbt`, using the https://github.com/gatling/gatling[Gatling Load Testing Framework] codebase as the example.
30
+
Gatling is a medium-sized codebase, 40,000 lines of Scala split over 21 subprojects.
31
+
By porting it to Mill, this case study should give you an idea of how Mill compares to `sbt` in more realistic, real-world projects.
32
32
33
33
In general, in the ideal case Mill and `sbt` have similar performance: caching, parallelism, incremental
34
-
compilation, and so on. Mill's main advantage over `sbt` is its simplicity:
34
+
compilation, and so on.
35
+
Mill's main advantage over `sbt` is its simplicity:
35
36
36
37
* You do not need to keep a live `sbt` session to maximize performance, exit `sbt` to run Bash commands,
37
38
or juggle multiple terminal windows to run `sbt` in one and Bash in another. Instead, you can just
38
39
run Mill like any command line tool, and Mill caches and parallelizes to maximize performance automatically
39
40
40
-
* Mill's IDE support is better than `sbt`'s due to how Mill is designed: peek-at-documentation,
41
+
* Mill's IDE support is better than ``sbt``'s due to how Mill is designed: peek-at-documentation,
41
42
jump-to-definition, find-overrides, etc. is much more useful since your IDE understands Mill
42
43
much better than it understands `sbt`.
43
44
@@ -54,9 +55,8 @@ change any other files in the repository:
54
55
== Completeness
55
56
56
57
The Mill build for Gatling is not 100% complete, but it covers most of the major parts of Gatling:
57
-
compiling Scala, running tests. It does not currently cover linting via
58
-
https://github.com/diffplug/spotless[Spotless], as that is not built-in to Mill, but it could be
59
-
added as necessary.
58
+
compiling Scala, running tests.
59
+
It does not currently cover linting via https://github.com/diffplug/spotless[Spotless], as that is not built-in to Mill, but it could be added as necessary.
60
60
61
61
The goal of this exercise is not to be 100% feature complete enough to replace the `sbt` build
62
62
today. It is instead meant to provide a realistic comparison of how using Mill in a realistic,
@@ -80,7 +80,7 @@ both scenarios above, along with the time taken for Mill commands. Mill does not
80
80
distinction, and can only be run directly from the command line. The Hot `sbt` mode only
81
81
reports timings to the nearest second, so that is the number used in this comparison.
82
82
83
-
The Mill build benchmarks for Gatling is generally much snappier than the Cold `sbt` benchmark,
83
+
The Mill build benchmarks for Gatling is generally much snappier than the cold `sbt` benchmark,
84
84
and comparable to that Hot `sbt` benchmark. Mill is marginally faster in the
85
85
`Parallel Clean Compile All` benchmark (10s vs 14s), but more importantly does not have the same
86
86
_Cold vs Hot_ distinction that `sbt` has: as Mill is always run "cold" from the command line and
@@ -205,10 +205,9 @@ in comparison substantial >4s overhead.
205
205
206
206
== IDE Support
207
207
208
-
One area that Mill does significantly better than `sbt` is in the IDE support. For example, although
209
-
IDEs like IntelliJ are nominally able to parse and analyze your `sbt` files, the assistance they can
210
-
provide is often not very useful. For example, consider the inspection and jump-to-definition experience
211
-
of looking into an `sbt` Task:
208
+
One area that Mill does significantly better than `sbt` is in the IDE support.
209
+
For example, although IDEs like IntelliJ are nominally able to parse and analyze your `sbt` files, the assistance they can provide is often not very useful.
210
+
For example, consider the inspection and jump-to-definition experience of looking into an `sbt` Task:
In general, although your IDE can make sure the name of the task exists, and the type is correct, it
222
221
is unable to pull up any further information about the task: its documentation, its implementation,
223
-
usages, any upstream overridden implementations, etc.. Some of this is the limitations of the IDE,
224
-
but some of it is fundamental: because `sbt` makes the developer define the `val myTask` separate
225
-
from the assignment of `myTask := something`, jumping to the definition of `myTask` tells you nothing
226
-
at all: what it does, where it is assigned, etc.
222
+
usages, any upstream overridden implementations, etc..
223
+
Some of this is the limitations of the IDE, but some of it is fundamental: because `sbt` makes the developer define the `val myTask` separate from the assignment of `myTask := something`, jumping to the definition of `myTask` tells you nothing at all: what it does, where it is assigned, etc.
227
224
228
225
In comparison, for Mill, IDEs like Intellij are able to provide much more intelligence. e.g. when
229
226
inspecting a task, it is able to pull up the documentation comment:
In general, navigating around your build in Mill is much more straightforward than
249
-
navigating around your build in `sbt`. All your normal IDE functionality works perfectly:
250
-
jump-to-definition, find-usages, peek-at-documentation, and so on. Although the Mill
251
-
and `sbt` builds end up doing the same basic things - compiling Scala, running tests,
246
+
navigating around your build in `sbt`.
247
+
All your normal IDE functionality works perfectly:
248
+
jump-to-definition, find-usages, peek-at-documentation, and so on.
249
+
Although the Mill and `sbt` builds end up doing the same basic things - compiling Scala, running tests,
252
250
zipping up jars - Mill helps de-mystify things considerably so you are never blocked
253
251
wondering what your build tool is doing.
254
252
255
253
== Debugging Tooling
256
254
257
255
Another area that Mill does better than `sbt` is providing builtin tools for you to understand
258
-
what your build is doing. For example, the Gatling project build discussed has 21 submodules
259
-
and associated test suites, but how do these different modules depend on each other? With
260
-
Mill, you can run `./mill visualize __.compile`, and it will show you how the
256
+
what your build is doing.
257
+
For example, the Gatling project build discussed has 21 submodules
258
+
and associated test suites, but how do these different modules depend on each other?
259
+
With Mill, you can run `./mill visualize __.compile`, and it will show you how the
261
260
`compile` task of each module depends on the others:
262
261
263
262
image::comparisons/GatlingCompileGraph.svg[]
264
263
265
264
Apart from the static dependency graph, another thing of interest may be the performance
266
-
profile and timeline: where the time is spent when you actually compile everything. With
267
-
Mill, when you run a compilation using `./mill -j 10 __.compile`, you automatically get a
265
+
profile and timeline: where the time is spent when you actually compile everything.
266
+
With Mill, when you run a compilation using `./mill -j 10 __.compile`, you automatically get a
268
267
`out/mill-chrome-profile.json` file that you can load into your `chrome://tracing` page and
269
268
visualize where your build is spending time and where the performance bottlenecks are:
270
269
@@ -307,14 +306,14 @@ take ownership of the build tool.
307
306
== Conclusion
308
307
309
308
Both the Mill and `sbt` builds we discussed in this case study do the same thing: they
310
-
compile Java and Scala code and run tests. If set up and used properly, `sbt` builds
311
-
are performant and do what needs to be done.
309
+
compile Java and Scala code and run tests.
310
+
If set up and used properly, `sbt` builds are performant and do what needs to be done.
312
311
313
-
Where Mill has an advantage over `sbt` is in its simplicity and understandability. You
314
-
do not need to worry about using it "the wrong way" and ending up with workflows running
315
-
slower than necessary. You can explore your build using your IDE like you would any other
312
+
Where Mill has an advantage over `sbt` is in its simplicity and understandability.
313
+
You do not need to worry about using it "the wrong way" and ending up with workflows running
314
+
slower than necessary.
315
+
You can explore your build using your IDE like you would any other
316
316
project, tracing task dependencies using the same jump-to-definition you use to trace
317
-
method calls in your application code. Mill provides builtin tools to help you navigate,
318
-
visualize, and understand your build, turning a normally opaque "build config" into
319
-
something that's transparent and easily understandable.
317
+
method calls in your application code.
318
+
Mill provides builtin tools to help you navigate, visualize, and understand your build, turning a normally opaque "build config" into something that's transparent and easily understandable.
0 commit comments