Fork me on GitHub
#clojurescript
<
2016-11-06
>
ben-orenstein00:11:30

Hey all! I've written and profiled some cljs and found that a reduce operation over a large vector is my current bottleneck. I've tried converting that vector to a js array so I can use areduce, but the cost of the conversion seems equal to the speed gain from areduce.

ben-orenstein00:11:13

Do I have any other options for speeding up the summation of a large (40k elements) vector?

gfredericks01:11:16

@ben-orenstein you could write it tediously inlined with loop and see if that makes a difference

gfredericks01:11:32

no higher-order functions

jrheard01:11:20

yeah, i’m not surprised that the conversion undoes your speed gain, i’ve done the same thing

jrheard01:11:14

this might be a job for transducers

jrheard01:11:52

i am not an expert on transducers, but i’m going to sketch out something that you could try - if you do try it, let me know whether it worked or whether i shouldn’t try to give advice on slack after dinner+beers with friends

jrheard01:11:23

god, no, i’ve lost it

jrheard01:11:18

anyway whatever. what i’m trying to communicate is that i hear that doing (into [] (map foo) bar) is faster than (map foo bar), particularly if you’ve got a pipeline of several map/reduce operations rather than just the one (map foo) operation

jrheard01:11:50

note that the invocation that gives you nice performance is (into [] (map foo) bar), not (into [] (map foo bar))

jrheard01:11:31

so if you can figure out the right syntax to chain your maps+reduces together and feed them to into, i recommend giving that a shot and measuring the performance before+after

jrheard02:11:19

(my understanding of this stuff is limited - this may only be relevant for situations where you’ve got a lot of maps/filters and not be relevant for reduce)

jrheard02:11:28

also i just tinkered around in planck and it looks like (apply + squares) is much faster than (reduce + squares) when squares is a super large vector. ok i’m turning off slack for the night before i get myself into any more trouble, good luck 🙂

mfikes03:11:38

@ben-orenstein Fooling around in non-`:advanced`, it looks like the calculation is dominated by the diffing and squaring, as opposed to the summation. If you fuse the two operations, you can shave off some time.

(defn calculate-fitness' [reference-image-data individual-image-data]
  "Takes two vectors of ints 0-255, representing the rgba data for our
  reference image and individual-image-data. Returns the sum of squares
  difference between the two, which represents how similar the two images are."
  (let [squared-diffs (map (fn [a b] (let [d (- a b)]
                                       (* d d)))
                        reference-image-data individual-image-data)
        sum-of-squares (apply + squared-diffs)
        maximum-difference (* (count reference-image-data)
                             (* 256 256))]
    (- 1 (/ sum-of-squares maximum-difference))))

rovanion09:11:12

Does anyone have any favourites or recommendations for approaching the consumption of a JSON-yielding HTTP API in cljs?

rovanion09:11:41

I'm thinking of something to keep me out of callback hell.

val_waeselynck09:11:47

@rovanion well, popular appraoches for dealing with asynchrony are core.async and promise libraries (such as promesa)

val_waeselynck09:11:16

what is specific to HTTP or JSON in your problem ?

rovanion09:11:23

We've got a REST API, if such a thing exists, that takes and delivers JSON. Nothing special about it really.

rovanion09:11:28

So perhaps in other words. Is there any one of the three httpurr, cljs-http and happy which is more suited for use with core.async? I see that httpurr has promises built in and that cljs-http returns core.async channels.

rovanion09:11:02

Mostly just seeking some wisdom though.

val_waeselynck11:11:19

@rovanion I don't think there's much at stake in the choice of the HTTP client library. My advice: pick an asynchrony paradigm which suits your application architecture, then pick an http library which is adapted to that paradigm (and still gives you all the configuration knobs you need, such as encoding formats, that's actually the more important thing as making a promise or core-async adapter really won't be hard in any case).

val_waeselynck11:11:44

Personally, I like using core.async channels which receive either a value or an Error. Not everyone does

lsenta11:11:48

Hi guys, my code is throwing Uncaught TypeError: Cannot read property 'cljs_test_each_fixtures' of undefined at me (running tests in figwheel) at random places. Any idea where that might come from?

lsenta11:11:14

I’ve already commented out all the fixtures

dbsgtk16:11:47

Hi all, I'm a clojure noob, and I'm using http://clojure.java.io in a clojure library, but only reading files into data structures at compile time. I'd like to read the same files (at compile time) in a clojurescript program. I've read that it's possible to use clojure IO at compile time, but am unsure how to do it. Can anyone point me to a simple example?

gfredericks17:11:51

@dbsgtk I think that would just be a macro

gfredericks17:11:06

(defmacro read-file [] (slurp file))

gfredericks17:11:14

and then (def file-contents (read-file))

futuro19:11:04

When I run in-ns in a clojurescript repl, does the fact that I can now references functions/variables in that particular namespace have anything to do with the analyzer keeping track of the namespace I'm supposed to be in and pre-pending that to all of my js calls? That is, has the Google Closure compiler already brought in all of my namespaces into the global context, so we can reference every function/variable by their full namespace?

futuro19:11:06

I've been trying to figure out how to create a js repl that had similar capabilities to the cljs repl, and being able to easily move between namespaces is one of the things I would love in the js world

futuro19:11:49

(There's more the the cljs compiler, for sure, this was just the first place I decided to start looking)

mfikes19:11:48

@futuro Namespaces are not automatically loaded—they need to be required

futuro19:11:07

@mfikes I'm confused by the invocation of goog.provide in cljs.repl if the namespace is missing from the analyzer (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl.cljc#L679)

futuro19:11:37

but assuming we've already required the namespace, what is in-ns doing?

futuro19:11:25

or maybe I should say, what affect does changing cljs.analyzer/cljs-ns have on evaluation?

mfikes19:11:10

@futuro: I gotta run, but the answers in this SO might help partially answer your question. http://stackoverflow.com/questions/35709098/using-required-namespace-in-the-repl

futuro19:11:32

@mfikes Thank you for 😄

futuro19:11:41

welp, that doesn't work

futuro19:11:50

I'll check out that link regardless

mfikes19:11:37

Short answer is in-ns is meant to switch you to an existing ns

futuro19:11:58

Yeah, I'm trying to figure out the internals of in-ns and how it allows me to reference variables/functions in a ns, and how this relates (or doesn't) to webpack and how it modularizes code

futuro19:11:12

I'll give that link a perusal and fire up a repl to do some more digging