This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-02-08
Channels
- # aleph (11)
- # arachne (7)
- # aws (1)
- # bangalore-clj (4)
- # beginners (24)
- # boot (128)
- # bristol-clojurians (23)
- # cider (1)
- # cljs-dev (43)
- # cljsrn (6)
- # clojure (178)
- # clojure-austin (3)
- # clojure-chicago (1)
- # clojure-dusseldorf (14)
- # clojure-finland (15)
- # clojure-france (6)
- # clojure-italy (18)
- # clojure-portugal (2)
- # clojure-russia (67)
- # clojure-spec (148)
- # clojure-uk (55)
- # clojurescript (199)
- # core-async (4)
- # cursive (18)
- # datascript (5)
- # datomic (120)
- # devcards (3)
- # dirac (53)
- # emacs (11)
- # events (3)
- # gsoc (7)
- # jobs (1)
- # lein-figwheel (25)
- # leiningen (5)
- # lumo (12)
- # off-topic (29)
- # om (174)
- # om-next (2)
- # onyx (7)
- # perun (10)
- # protorepl (6)
- # re-frame (12)
- # remote-jobs (1)
- # ring (19)
- # ring-swagger (25)
- # rum (6)
- # spacemacs (13)
- # sql (3)
- # untangled (88)
- # yada (7)
@pesterhazy @pithyless @bhagany @ska @alandipert
Thank you guys for your responses.
I tried time BOOT_JVM_OPTIONS="-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xmx2g -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -Xverify:none" boot -BPh
and indeed I was able to cut down on the time:
BOOT_JVM_OPTIONS= boot -BPh 3.55s user 0.30s system 54% cpu 6.989 total
However, it is still taking much longer than a number of you guys are getting. One thing I did discover was in my boot.properties file - key values are not properly read if the string sprawls multiple lines: is this a bug?
boot.properties
BOOT_CLOJURE_NAME=org.clojure/clojure
BOOT_CLOJURE_VERSION=1.8.0
BOOT_VERSION=2.7.1
BOOT_LOCAL_REPO=./third_party_dependencies/
BOOT_HOME=/.boot
BOOT_AS_ROOT=yes
BOOT_JVM_OPTIONS="-client-XX:+TieredCompilation -XX:TieredStopAtLevel=1
-Xmx2g
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-Xverify:none"
Output from boot show βenv
:config
{"BOOT_AS_ROOT" "yes", "BOOT_CLOJURE_NAME" "org.clojure/clojure", "BOOT_JVM_OPTIONS" "\"-client-XX:+TieredCompilation -XX:TieredStopAtLevel=1", "BOOT_FILE" "build.boot", "BOOT_CLOJURE_VERSION" "1.8.0", "BOOT_VERSION" "2.7.1", "BOOT_LOCAL_REPO" "./third_party_dependencies/"},
^^ Turns out I should have written it like this:
BOOT_CLOJURE_NAME=org.clojure/clojure
BOOT_CLOJURE_VERSION=1.8.0
BOOT_VERSION=2.7.1
BOOT_LOCAL_REPO=./third_party_dependencies/
BOOT_HOME=/.boot
BOOT_AS_ROOT=yes
BOOT_JVM_OPTIONS=-client \
-XX:+TieredCompilation \
-XX:TieredStopAtLevel=1 \
-Xmx2g \
-XX:+UseConcMarkSweepGC \
-XX:+CMSClassUnloadingEnabled \
-Xverify:none
I managed to reduce my boot time to a more reasonable level:
boot -BPh 10.12s user 0.48s system 285% cpu 3.711 total
time BOOT_JVM_OPTIONS="-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xmx2g -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -Xverify:none" boot -BPh
boot -BPh 3.61s user 0.26s system 192% cpu 2.015 total
I uninstalled boot with Brew. Furthermore, I deleted the ~/.boot directory. Could the slowdown be due to the cache getting too large?
Hmm, -Xverify:none
... hadn't tried that...
Oh BOOT_AS_ROOT
is new to me, we'd better add tests π
Heh, that not being the default has saved me more than once...
Oh I bet, and <paranoia>
I would review the code twice if I had to enable something like that </paranoia>
After not touching leiningen in 1.5 years, I just tried lein-figwheel and it's great! It's made so much progress since I last looked at it.
My favorite feature now is that it automatically opens a repl prompt in the terminal - that's great usability.
I'd love to see this in boot as well, but can't see an easy way to make this happen
@pesterhazy you need 2 separate terminals right?
one thing I thought would be useful would be to start a socket repl that provides a cljs repl
then open another terminal window (shell out to xterm or whatever) and have that telnet into the socket repl
@pesterhazy There is a slight limitation in boot's model in that you can't have a REPL-y running & a watch
(this may be wrong, but I know no workaround)
But if you're looking at that sort of craziness, is it that much more helpful than having the user hit Ctrl-Z then running boot repl -c
to connect back to their REPL? Then there's a function (cljs-repl)
I believe which gets them the REPL prompt for cljs.
yes but that's super hacky
and worst of all, not automated
it's better to be able to point people in your team to a single command (`boot dev`) that does all the work
@micha mentioned a way to combine watch
with repl -c
.. you can run boot repl
and then run the main pipeline from there, in a future
still that seems sub-optimal as you lose the error output from the cljs compilation
I don't think that is hacky. The nREPL isn't a single interface. It's two things, a server and a client. I launch a server as part of my development, if I want a TUI to interface with the REPL I can launch one (conveniently) from boot! Or I could use something like parle, or the traditional editor integrations too.
Yeah, I really can't see why you consider that hacky. Automation can be handled by this: boot dev & && boot repl -c
Also, I'm pretty sure when a backgrounded process prints to stdout, you get a message. Not sure how REPL-y handles that, but you might still get the cljs build failure.
IMO Unix shell job handling just doesn't work particularly well
what's parle?
@pesterhazy I've had opposite experiences with unix shell job handling. I run my entire status panel using a series of HUP'd tasks and FIFO pipes across processes. I've never had an issue with it.
I'll check out parle
just tried out opening a cljs repl in a separate terminal window, it's pretty easy
i.e. socket server functionality makes this pretty easy
I think I can also just reload the buffer in cider, not sure why that works
@pesterhazy also in the latest cider
on jack-in-clojurescript it opens two repl buffers one of which is directly in cljs.user
-> https://github.com/clojure-emacs/cider/pull/1928
That's great , I knew it would have happened sooner or later https://github.com/kanej/parle
the jar task makes it easy to write an entry to the manifest. what's the best way to read an entry? i need to pass some metadata to the jar consumer (another boot task).
@mobileink you can use the java.util.jar.Manifest class
like here http://stackoverflow.com/questions/19347052/using-java-to-read-a-jar-manifest-file
see also https://docs.oracle.com/javase/7/docs/api/java/util/jar/JarFile.html#getManifest()
thanks, didn't know about that. wonder if it's worth adding some convenience fns for this to boot. e.g. (defn manifest-map [jar] ... ) or sth like that.
The only thing I use a JAR manifest for is the Main attribute... I imagine that's probably true of many clojure devs
@geoffs: agreed, not so common, probably. but underappreciated, imho; really useful for meta-programming with boot tasks!
really? do you have an example project that does that? I'm not really sure I understand what you're talking about π
not quite ready for the masses, but: i have a clojure lib
miraj.polymer.paper
that "wraps" the paper components of https://www.polymer-project.org/1.0/. the consumer is a webpage project that does
(:require [miraj.polymer.paper :as paper])
. my compile
task turns that into <link ... > elements in a generated html file.for this to work, the href in the link elements must be resolvable. that's where the manifest comes in. it contains an entry specifying the bower cmd needed to download the polymer assets. so the
compile
task must also read the manifest to get the bower cmd, run bower, and put the obtained assets into the fileset.this way the consumer of the lib does not have to worry about asset config - the writer of the wrapper lib, plus the structure of the boot task lib, handles everything, magically.
btw this assumes that the webpages will be static, generated from clojure code at build time but served directly by the http server at runtime.
make sense? i guess it's a little complicated, but in the end the complexity will be hidden.
anyway, key point being is that the manifest is a nice jar-level task communication mechanism. in earlier versions i relied on edn files, so the webpage programmer had to configure stuff to make the lib/jar work. then i realized the manifest would obviate the need for that. luv zero-config stuff!
i hate needing to run bower, npm, etc. and then having to make sure my <link...> elts are correct, etc., just to set up a web app before i even start coding the app. i don't have to do that to write a clojure app, :require et al. just work; why shouldn't webapp dev be just as easy?
I like the goal π still a bit unclear on the details, but it definitely sounds interesting
stay tuned, this is about my 3rd iteration so i may even be able to explain it clearly. π
meanwhile this might help a bit: i put some metadata on the namespace var of miraj.polymer.paper
. that's what allows my compile
task to do the right thing; it filters the result of all-ns
to find the stuff it understands.
shite and onions. just realized i do not need the manifest. i can just add the info needed to the ns metadata. amazing what you learn about your own stuff when you try to explain it to others!
wait. i swear this was broken before i showed it to you. i can't understand why it's working now!
the biggest boot command I have ever run:
boot -B --source-paths "." watch -e "^mvn-target" sift -i "src" -i "pom.xml" mvn -W `pwd` -A "-Pboot-clj clean install" target
howsabout "most granular boot tasklib"? i got about a dozen tasks for boot-gae, and i'll bet i could get some more. π
i have several boot libs in the works designed to work together via composition. wondering how many boot tasklibs are independent v. depending on other boot tasklibs.
more generally: what does it take to make your boot tasks play nice with tasks from another boot lib?
@mobileink just call the next handler with the fileset should suffice
ah idempotence, depending of what yes
yes ok, but that is more of task logic
if you look at the boot side of things
the only thing you need to do is to call the next handler
maybe what i'm wondering is more along the lines of "how to make public the assumptions your tasks make".
I think that's the power of a middleware, no assumption should leak
e.g. i have some libs that work together, but only because they assume there is an edn file of particular form in the fileset.
if two tasks need to communicate, there is some leakage, but if you talk about one task none should happen
yep in that case you need to coordinate
task ordering, also can be tricky
its a tradeoff tho
yes, I remember we spoke here a couple of times about using something like a tree structure for composing tasks
but it complicates things
I wish Slack had history now π
the one feature I really want from boot .-- a HUD like control display implemented in the browser
I want boot interfaces that I can, drag/drop, toggle, expand/collapse, and visualize statistics about
@alandipert: yeah, ordering. idempotence. you can do it, but it involves overhead. in my case, tasks look for a master config edn. to get idempotence, if they don't find it they must create it. cost/benefits i guess.
boot-cljs
and boot-reload
kind of do the same thing
and then, if i want to use tasks from different libs in one pipeline, they must agree about dealing with the master confog edn and its structure.
I mean, you could have a task which creates a bus/queue and then your tasks will grab/put things on there...but is it worth it?
what if we could annotate tasks somehow to stipluate what they expect to see in the incoming fileset?
could do that now, with preconditions?
ie a precondition in the fileset-receiving fn that a task returns
preconditions or spec, it is kind of a similar approach I guess
i guess the precondition would be the place to put the calls to spec, maybe
along with some boot code to pull the file out that you expect
yep I was thinking the same
there could be spec in the meta of the task var
little bit of automation
but it is not a user-facing feature
so let's back up a bit. does it make sense to expect that any boot task can be composed with any other boot task? prolly not. but there is a subset, where tasks from different libs should be expectedvto play nice together. puts me in the mind of protocols.
yes in that case you would have maybe a compatibility or spec register for this or that task
boot-servlets would need to publish something that tell the dev what needs to be done to interop.
it would need to say, somehow, here's what the fs should contain, with this format.
I think at the moment not many tasks have this necessity so that's maybe why it has not been developed yet
early days! π once people begin to understand that boot obsoletes all other such tools we'll see many more use cases. let's not forget that boot is not really a build tool, it's more of a job control language.
ah ah well yeah, I have for example the with to convert as many namespaces as I can to .cljc
and see it running on node.js....maybe another life π