Fork me on GitHub
#tools-build
<
2023-10-23
>
flowthing09:10:22

Working on migrating from Leiningen to tools.deps/tools.build. clojure.tools.build.api/uber takes a very long time to finish:

(time (build/uber
       {:class-dir class-dir
        :uber-file "target/server.jar"
        :basis basis
        :main 'foo.main}))
"Elapsed time: 296066.973708 msecs" ; ~5 minutes
nil
Compared to lein uberjar:
λ time lein uberjar
...

________________________________________________________
Executed in   44.17 secs    fish           external
   usr time   20.59 secs    0.10 millis   20.59 secs
   sys time   11.67 secs    1.56 millis   11.67 secs
(Which includes two JVM startup times, AOT compilation, nREPL & Leiningen overhead, etc.) Is this expected?

flowthing09:10:13

Actually, I wonder if it might be the old corporate antivirus software interference story once again...

jpmonettas10:10:55

have you tried https://github.com/clojure-goes-fast/clj-async-profiler on it? I think wrapping that in a prof/profile instead of time should tell you where all that time is going

flowthing10:10:42

I haven't yet. I'll give that a try. 👍

flowthing11:10:58

The resulting uberjar is 29M, so nothing out of ordinary.

jpmonettas11:10:11

yeah I don't see anything that catches my attention there :thinking_face:

jpmonettas11:10:53

I don't see the GC activity on the graph, was there any?

flowthing11:10:13

I don't know. I'm not very adept at using clj-async-profiler. 🙂 Here's the HTML version if you want to take a look.

jpmonettas11:10:06

that small thing in yellow on the right shows GC and Hotspot compilers activity, but is very small

flowthing11:10:29

Right, thanks. 👍 At least I learned something new. 🙂

flowthing11:10:49

Maybe I'll try strace or whatever the macOS equivalent is...

jpmonettas11:10:22

yeah could be a good idea, if you grep out all those pesky futex calls

flowthing11:10:21

Unless I'm foiled by System Integrity Protection...

jpmonettas11:10:26

or you can also run the profiler for the lein process and compare the flamegraphs? maybe there is something there. You can download async profiler https://github.com/async-profiler/async-profiler, unzip that into a folder, and then what I do is run ./profiler.sh -e cpu -d SECONDS_TO_SAMPLE -f /tmp/flamegraph.html YOUR_LEIN_PID

jpmonettas11:10:58

so you can run that against any java process and it will give you the flamegraph

flowthing11:10:21

Thanks, I'll give that a try if the dtrace path is a dead end. 👍

👍 1
seancorfield14:10:34

I can't remember whether Leiningen explodes all the JARs on the classpath into the target/classes folder before building the uberjar -- I suspect it doesn't -- so if you have antivirus software checking every new file created, tools.build.api/uber is going to be badly affected since it explodes JARs and copies everything into the target tree first, then assembles the JAR from all those files... lots of file activity. (depstar originally did that in two passes but I switched it to copy everything directly into the JAR, exploding JARs on the classpath only in memory -- made it run over 2x faster every without virus checking)

flowthing15:10:08

That definitely sounds plausible, thanks. 👍:skin-tone-2:

salam16:10:44

We use https://github.com/tonsky/uberdeps (which “does not unpack intermediate JARs on disk.”) in our tools.deps projects. The poor performance (even on a Mac without antivirus software) of tools.build.api/uber is the only reason that’s preventing us from switching to it.

🙏 1
flowthing16:10:11

I see, thanks. I used to use uberdeps before tools.build was a thing, but I think I’ll give it a try to see how it compares. 👍:skin-tone-2:

👍 1
seancorfield18:10:10

Cool. Can you get it configured to ignore certain folders? I've generally found antivirus software to be pretty problematic for developers in any situation where code is getting compiled or build systems are shuffling a lot of files around...

flowthing18:10:04

I believe there was an opportunity to do something like that at my previous job, but it used a different AV program... I'll have to ask around.

flowthing19:10:11

Yeah, I can reproduce the issue with e.g. https://github.com/seancorfield/usermanager-example. I'm on a pretty beefy MacBook Pro M2, and (b/uber (uber-opts {})) takes over a minute, whereas on a much less capable Linux box (with no corporate malware) it takes ~5 seconds.

seancorfield20:10:25

Thanks for confirming that @U4ZDX466T -- Hopefully, you can address the situation with your IT team because I would expect that A/V tool to slow down a lot of software development tasks.

🙏 1
flowthing05:10:49

Just one final comment for posterity, in case anyone finds this thread via Slack search or something: I added exclusions for the folders I use for dev via Virus & threat protection settings » Manage settings » Add or Remove Exclusion... in Microsoft Defender (which our corporate policy luckily allowed), and that made a big difference: building an uberjar via clojure.tools.build.api/uber now takes ~45 seconds instead of 5 minutes.

🎉 2