Fork me on GitHub
#cljs-dev
<
2016-12-14
>
plexus10:12:14

I was browsing core.cljs and came across a bunch of metadata that I assume are hints to the compiler: ^native, ^not-native, ^clj, ^clj-or-nil... what do these do? are they documented anywhere?

tmulvaney10:12:51

@plexus they let the compiler optimize some things. For example if you tag something as ^boolean the compiler can elide the truth check

tmulvaney10:12:08

For example if you compile (if (my-predicate? some-data) ...) the resultant javascript will likely have wrapped the result of that expression in the truthy check but if you tag it: (if ^boolean (my-predicate? some-data) ...) it won't as it now knows the function returns a javascript boolean.

tmulvaney10:12:13

The truthy check is at line 881 of clojure/cljs/core.cljc btw. You can see its a template for some javascript.

thheller10:12:17

@plexus as tmulvaney said: they are internal compiler optimizations that you should almost never have to worry about. don't think they are documented anywhere though.

thheller10:12:30

not-native is for protocol dispatch

plexus10:12:06

Thanks, I'll poke around the compiler to see what they influence then

thheller10:12:25

usually the compiler will check for a protocol before calling it .. x.my$super$Protocol$Fn ? x.my$super$Protocol$Fn(...) : my.super.protocol-fn(x, ...) with not-native this check will be skipped and directly call x.my$super$Protocol$Fn

thheller10:12:03

names are not correct but you get the idea 😉

rauh10:12:17

@dnolen Sorry to bother again: So I noticed there is quite a few usages of declare in core. I also noticed s a (def ^{:declare true, :arglists '(...)} foo-fn) isn't respected by the compiler and will still generate the check if the arity actually exists. So: 1. Should the compiler respect the arglists and generate the optimal code? 2. Should there be a "better" declare for cljs to provide arglists (declare-fn get [m x] [m x nf])? Besides the generated check being never invoked, which might be completely optimized away by most engines, I found 3 cases where cljs.core always goes thru the .call syntax in potential hotspots: - cons used in IndexedSeq.conj and Rseq.conj - key+val in conj! of ITransient

thheller10:12:58

@rauh interesting idea, did you check how clojure handles these things?

thheller10:12:36

hmm I don't even know if clojure does some of the tricks cljs does, probably not 😛

rauh11:12:09

@thheller I'm no JVM expert, but arent' they all eventually methods of a Java class? So if they get invoked it'll invoke the right arity fn and will throw if that arity doesn't exist (JS will be ok with calling fns with the wrong arity).

rauh11:12:49

Hence I never use constantly in cljs, but do in clj.

thheller11:12:18

I always wondered if CLJS could optimize some expressions more (ie. (def x (fn [])) (def x (let [priv (atom {})] (fn [...]))) but never bothered enough to investigate

thheller11:12:36

so I'm kinda interested in your findings 🙂

dnolen13:12:51

@rauh not interested in solutions until first it’s demonstrated there will be some significant performance benefits, so I would collect some numbers first

dnolen13:12:31

I do not expect it will matter for anything except declare for single arity fns, and probably even then possibly not significant enough

dnolen13:12:00

lets get some profiles and find out

dnolen13:12:11

@plexus not documented anywhere and you should avoid them - ^boolean is the only one close to “official"

plexus13:12:54

Thanks @dnolen , I'm mostly satisfying my curiosity

dnolen13:12:52

@plexus with the exception of ^boolean they are all half-baked, I don’t think you’ll discover anything consistent 🙂

rauh13:12:24

@dnolen on my Chrome v54, it looks like the difference is less 5%, 😕 . So the only benefit would be slightly smaller code size, but that's probably even less than 1% difference

dnolen13:12:25

@rauh we do factor in other browsers, if you have time to test Safari/Firefox that’s useful

dnolen13:12:57

yeah, not concerned about code size here

rauh13:12:07

@dnolen Good call, Firefox was a factor of 2.23 faster 🙂

dnolen13:12:29

so that’s significant

rauh13:12:38

That's for conj! on TransientHashMap.

rauh13:12:04

No Safari so can't test that.

dnolen13:12:31

not a big deal

dnolen13:12:00

so back to your idea - I’d be ok with a patch for allowing that kind of meta

dnolen13:12:04

not interested in sugar at all

dnolen13:12:28

feel free to open a minor enhancement ticket in JIRA and add a patch at your leisure

rauh13:12:35

So you mean a (def ^{:declare true :arglists ...} get) should be understood by the compiler?

dnolen13:12:23

@rauh yes I’m ok with the idea, now to see if a reasonable patch is possible

dnolen14:12:22

@rauh I took a quick browse, it’s not a simple patch, you can definitely expect to be a moderate ClojureScript compiler expert after your done 🙂

dnolen14:12:30

happy to answer any questions if you decide to take this one on

rauh14:12:59

@dnolen Sounds good, thanks. I might take a stab at this in the new year at some point. http://dev.clojure.org/jira/browse/CLJS-1871