Fork me on GitHub
#clojure-dev
<
2018-01-15
>
rauh14:01:55

How come RT.boundedLength doesn't check for Counted? Also it could be made more efficient for chunked sequences. Would potentially speedup apply

alexmiller16:01:57

it’s probably usually called with non-Counted instances, but feel free to make a ticket

bronsa16:01:50

bounded-lenght does that check in clojure

bronsa16:01:56

err, bounded-count

alexmiller16:01:01

as with any perf ticket, it is helpful to include test results that illustrate the perf improvement of the change when it helps and also any cases that have costs (adding an instanceof check will slow down the non-Counted case)

alexmiller16:01:17

yeah, that’s a totally different path I think

bronsa16:01:59

right, and what’s to note is that for bounded-count it’s not just a performance optimization, it changes the behaviour

alexmiller16:01:45

that’s also a fair thing to consider if same is true here

bronsa16:01:03

because it’s implemented as (if (counted? x) (count x) loop/recur) rather than (if (count x) (min (count x) bound) loop/recur)

bronsa16:01:39

(it surprised me a couple of times)

alexmiller16:01:42

yeah, you wouldn’t want that here

rauh17:01:03

I see, that makes sense. I haven't dabbled on the Java side of clojure but I might run some tests at some point. It's very likely be worth it if the bound was high. Admittedly which is seldom. Usually people keep their fixed args to <5 or so.

rauh17:01:16

All the apply/applyTo code is super old and could likely be sped up a bit. Maybe even use chunked sequences while plucking out the fixed arguments.

rauh17:01:02

In CLJS I got it faster than Clojure, which made me check out the implementation...

rauh17:01:29

Eg (apply a b c d xs) first builds up a bunch of Cons, just to later iterate over them for counting, then iterating over it again for plucking out the arguments. Then to finally call the fn.

alexmiller17:01:56

it wouldn’t surprise me if there were improvements to be made. considering the distribution of arg cases (obviously not uniform and weighted towards fewer) and actual class cases, it’s hard to predict overall impact

alexmiller17:01:28

to screen this I would want to understand what the distribution is in actuality both in terms of classes and size (usually I build a debugging patch that captures and records this info)

alexmiller17:01:36

and I would want to understand expected performance differences for some of the points in that space. For example, I expect ArraySeq, PersistentList, Cons etc to be common classes - how do each of those change in perf on invocation of different sizes, etc

alexmiller17:01:20

and then it’s useful to actually try something at an aggregate level to see if there is any observed perf difference in a real use case

alexmiller17:01:03

some hefty computation that involves a lot of invocation but little concurrency that can be easily re-run would be ideal

rauh17:01:47

I see. I'm guessing that'd be a big project. Probably could use heuristics (`if getRequiredArity() < 3 fallback-to-naive-first-next()`) to not impact current performance baseline. But yeah, it's probably not as simple as in CLJS I guess 🙂

alexmiller17:01:55

yeah, that’s the kind of work I typically do for perf improvements in Clojure :)

alexmiller17:01:36

doing the case analysis and simple timings wouldn’t take that long and should suggest whether this is a good idea and how much additional effort to put into it

alexmiller17:01:40

adding additional checks has its own cost on inlining, so you want to minimize those too

rauh17:01:04

A noob question: When do you do Java dev on Clojure, do you just have to recompile the entire project on every change or is there some smart way to stay in the REPL even after editing the java code?

alexmiller17:01:07

I think a check for Counted is likely fast and probably common enough to be worth doing

alexmiller17:01:40

I usually recompile. there are ways to do Java code reloading but I don’t really trust them, esp if trying to evaluate perf changes

rauh17:01:03

got it. Thanks for your input. Appreciate it.

alexmiller17:01:31

you can do a full build of Clojure (Java + Clojure AOT) in about 15 s

alexmiller17:01:49

usually I spend a lot longer changing the code than that :)

alexmiller17:01:24

just mvn compile to rebuild

bronsa17:01:32

@rauh I use

compile-clojure () {
    pushd $HOME/src/clojure
    rm -rf target
    mvn install -Dmaven.test.skip=true
    popd
}

rauh17:01:26

@bronsa Thanks for the snippet. Saved 🙂

alexmiller17:01:29

mvn install does a lot more work (packaging and deployment)

alexmiller17:01:46

I guess it depends how you expect to use it

bronsa17:01:49

yeah use install if you care about using the SNAPSHOT version from e.g. clj

rauh17:01:16

Doesn't Java 9 introduce some Java compiler Interface? Just to code until the impl is working. Then proper compile for performance testing..

alexmiller18:01:02

I don’t know of anything new in java 9 for this - stuff has been there for a while to support hot code reloading. But in practical terms what you need to do to make that work is a lot more intrusive than just recompiling.