Fork me on GitHub
#clojure
<
2019-04-23
>
macrobartfast03:04:55

I'm finally getting productive with clojure, but now I'm finding out that sizable (read: useful) projects take forever to load a repl (I use cider/emacs)... we're talking a couple minutes per bounce... what am I doing wrong?

Alex Miller (Clojure team)03:04:25

if you're using user.clj and a very recent JDK version, you might have stumbled into a Java performance regression

Alex Miller (Clojure team)03:04:52

jdk 1.8u202+, 11.0.2, 12, etc

Alex Miller (Clojure team)03:04:37

you could try downgrading your java version or upgrading Clojure to 1.10.1-beta2 to see if that helps

seancorfield03:04:08

@macrobartfast As a sanity check, I just timed my REPL startup time -- via clj with a profile that contains every single dependency our 80,000+ line Clojure project uses, which also starts a Socket REPL and starts up Cognitect's REBL tool. A cold start to a live REPL with REBL open takes just under 12 seconds on my Mac.

macrobartfast03:04:43

ok, so it's something wrong with my setup, for sure.

macrobartfast03:04:05

and that's crazy fast, btw.

seancorfield03:04:09

Per Alex, it could be the JVM regression if you're on either of those versions...

seancorfield03:04:27

I think 12 seconds is slow 🙂

macrobartfast03:04:07

java version "1.8.0_92" Java(TM) SE Runtime Environment (build 1.8.0_92-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

seancorfield03:04:54

(without REBL and the Socket REPL, starting a plain REPL takes about 8 seconds for comparison)

seancorfield03:04:34

OK, so on that version of Java/JVM it's unlikely to be the regression Alex mentioned.

macrobartfast03:04:56

it's very likely something wrong with my code, right?

macrobartfast03:04:04

I mean, that can affect things, I'm guessing.

seancorfield03:04:10

Maybe ask in #cider and/or #emacs and see if they can suggest ways to optimize startup?

macrobartfast03:04:22

sounds like a plan.

macrobartfast03:04:43

I could generate a new project and see how long that takes.

seancorfield03:04:43

Also, I'm starting a REPL into the user namespace which means it doesn't need to load my main namespace.

macrobartfast03:04:06

lein repl on a project generated with

lein new app test
took about 11 seconds.

seancorfield04:04:20

(! 780)-> lein new app timing
Generating a project called timing based on the 'app' template.
(! 781)-> cd timing
(! 782)-> time lein repl < /dev/null
nREPL server started on port 57337 on host 127.0.0.1 ...
timing.core=> Bye for now!

real	0m7.290s
user	0m5.564s
sys	0m0.490s
(! 783)-> time lein repl < /dev/null
nREPL server started on port 57351 on host 127.0.0.1 ...
timing.core=> Bye for now!

real	0m6.634s
user	0m5.467s
sys	0m0.486s
(! 784)-> 
6.6 vs your 11.

macrobartfast04:04:07

ok, both are close enough for me 😉

seancorfield04:04:20

Leiningen adds a lot of overhead, compared to the CLI/`deps.edn` stuff, just FYI:

(! 787)-> clj -A:new app timing.core
Generating a project called timing.core based on the 'app' template.
(! 788)-> cd timing.core/
(! 789)-> time clj < /dev/null
Clojure 1.10.1-beta2
user=> 

real	0m4.462s
user	0m11.724s
sys	0m0.563s
(! 790)-> time clj < /dev/null
Clojure 1.10.1-beta2
user=> 

real	0m1.385s
user	0m2.742s
sys	0m0.194s
(! 791)-> 
6.6 goes down to 1.4 🙂

macrobartfast04:04:00

I'll also look at the CLI/deps.edn stuff, which I know nothing about.

seancorfield04:04:11

We love it. We switched from Boot to CLI last year (after switching from Leiningen to Boot just over three years ago).

macrobartfast04:04:16

I usually just lein repl at the root of the project... how would I specify a namespace?

seancorfield04:04:54

It depends what's in your project.clj -- when the REPL starts, is it in user or some project-specific ns?

macrobartfast04:04:25

so it's not that.

macrobartfast04:04:49

it is a big luminus rest service type thing, so it's a larger project.

jumar05:04:08

I've also found (and it was a long time ago) that luminus-based projects have quite a long startup time; and it was a very simple service actually. It's perhaps because of many depedencies it introduces...

macrobartfast04:04:17

well, you've given me a few things to look at in the morning.

macrobartfast04:04:36

probably is something to do with cider/emacs and all that, per what you were saying.

macrobartfast04:04:02

thanks for all the help!

Alex Miller (Clojure team)04:04:08

the luminus setup usually has a user.clj file and loads (and compiles) a large set of your project and dependent files on startup. I would look more carefully and see if you're doing something at the top level somewhere in addition to that too.

Alex Miller (Clojure team)04:04:20

like def'ing something that loads from a database, et c

Alex Miller (Clojure team)04:04:41

you can often use a delay to avoid doing that too eagerly

didibus04:04:30

Any way to spec something as a list or a cons? Is there a pred for that? Basically, I want a pred for clojure code

didibus04:04:38

To spec a macro

didibus04:04:26

Hum, looks like seq? could do

Alex Miller (Clojure team)04:04:35

generally, I find it's best to spec inputs to macros using the regex ops

didibus04:04:43

I have (s/+ seq?)

didibus04:04:56

Where it takes one or more s-exprs

didibus04:04:44

Would you do something different?

Alex Miller (Clojure team)11:04:46

I would prob do (s/+ any?)

Alex Miller (Clojure team)11:04:28

There are a lot of valid Clojure forms that are not seqs

didibus15:04:04

Thanks, I'll have a look at it again. I guess I'm not sure why I ever tried to restrict it in the first place.

Alex Miller (Clojure team)16:04:23

usually not worth it in macro args

Ivan Koz07:04:45

whats the difference between fn and fn*? Can't find a declaration of latter.

seancorfield07:04:20

fn is technically a "special form" but it is implemented as a macro that calls fn* which is part of the compiler

seancorfield07:04:16

Like let is a special form too, but it is also implemented as a macro that uses let*...

mhuebert10:04:00

I am writing some cljc code and realizing that there must be something about JVM-clojure and namespaced type hints that I don’t understand. If I have a type/record, I seem to be able to use its name as a type hint within its own namespace, but not from another namespace? example: https://gist.github.com/mhuebert/3269ac0b5bebebb93de9c497a33a694f

arbscht10:04:47

@mhuebert in jvm clojure MyType will be a generated class, you'd need to import it

mhuebert10:04:30

@mail462 ah, ok, thanks!

bronsa11:04:22

you don't necessarily need to import it, you simply need to refer to it as a class rather than as a Var

bronsa11:04:34

n/T is not valid syntax for classes in clojure/jvm

bronsa11:04:18

it needs to be n.T (namespace aliases are not valid either,`n` must be fully qualified)

bronsa11:04:40

it's unfortunate that clojure script diverged for deftypes

mhuebert11:04:10

so I guess it needs to be ^hints.my_type.MyType - also munging the - to _

arbscht11:04:46

yes -- import would just allow shorter naming, MyType (closer to t/MyType from the example)

mhuebert11:04:16

so (:import hints.my_type.MyType)

mhuebert11:04:44

and then I suppose I would refer MyType in the cljs version, so that a plain ^MyType annotation works for both

Ivan Koz15:04:15

does subvec allows for garbage collecting of unused nodes say if we want [1 2 3] -> [2 3] what is my options aside from vec -> seq -> vec

Alex Miller (Clojure team)15:04:05

ideally, don't use a vector in the first place if you need to remove elements any place but the end

Alex Miller (Clojure team)15:04:45

subvec will keep the original vector in memory so will not be gc'ed

Ivan Koz15:04:06

alex, thanks for everything you are doing for us btw, i'm a fan 😃

40
💯 32
🙏 12
fan 8
sobel16:04:26

is there a way to set use-context-classloader false before clojure starts?

Alex Miller (Clojure team)16:04:48

how are you starting clojure?

souenzzo17:04:03

How do i create a var in a another namespace? I know that it is not common, but I'm doing a DSL that "compiles" to #clara, and clara use vars in namespaces...

aria4217:04:58

Hey all, we’ve written a post on the Amperity Eng blog on Greenlight (our Clojure integration testing library). https://eng.amperity.com/posts/2019/04/greenlight

20
🚦 12
orestis18:04:17

Oh wow that is seriously cool. I’ve seen the project before but never got the value proposition. Are you aware of https://github.com/caioaao/kaocha-greenlight ? I’m using kaocha for running other tests.

orestis18:04:55

Silly question, can all the clojure.test compatible assertions be used?

aria4221:04:37

Hey @U7PBP4UVA thanks we have seen that. I think the answer to your question is yes they should work. Feel free to file an issue if you find out this isn’t the case

jeroenvandijk09:04:57

@U5JFWFE2V Looks good! Am I right to observe that the step idea has some overlap with ideas from Cucumber? Or is that just accidental?

aria4216:04:29

I certainly don’t know anything about it, but can ask internally from contributers

sobel17:04:42

@alexmiller java -jar [uberjar] args

sobel17:04:48

this code runs when i 'lein run' it but some jars fail their static initializers that try to classload XML expecting to get the system classloader (AFAIK)

Alex Miller (Clojure team)17:04:39

user.clj is loaded pretty early in the RT - you could try adding one that sets *use-context-classloader*