hoplon

The :hoplon: ClojureScript Web Framework - http://hoplon.io/
2018-06-27T16:38:45.000056Z

@jjttjj you might consider circumventing that question entirely and go straight to a walk-kids macro that works like (walk-kids deep-v [kid] ...)

2018-06-27T16:39:19.000274Z

it looks like merge-kids and add-children could be easily modified to do their iteration that way

2018-06-27T16:39:30.000062Z

(vs iterating through the value produced by vflatten)

2018-06-27T16:39:43.000511Z

parse-args looks a little trickier but it might be doable

2018-06-27T16:41:07.000272Z

actually yeah, definitely doable in the case of parse-args - i think you just need a helper function you'd call in two places, that takes the kids transient and args, and iterates/conj!es using the macro

2018-06-27T16:41:55.000597Z

maybe (dokids [kid v] ...) is a better name/convention

kennytilton 2018-06-27T17:09:41.000545Z

I just noticed something. There goes the reactive neighborhood: https://github.com/Microsoft/satcheljs (they use MobX underneath)

kennytilton 2018-06-27T17:11:02.000166Z

Speaking of reactive, I just did a Reagent app, treating ratoms and track! like our cells. Feels very similar. Anyone else pick that up.

2018-06-27T17:12:23.000334Z

hmmm i've started attempting to do some profiling to actually figure out where the bottlenecks are. am I correct that you're saying that we should have something that to prevent multiple iterations from occurring, ie once for vflatten, then again for whatever it is we need to do? Like, a quick and dirty way to check this would be to just add a function argument to vflatten and apply that to each leaf during the flattening process, that's what you're saying right?

2018-06-27T17:12:27.000127Z

@alandipert

2018-06-27T17:13:28.000180Z

I tried what i described, adding a function argument to vflatten but it doesn't seem to meaningfully effect the whole performance

2018-06-27T17:19:47.000015Z

add-children definitely is one of the things taking up significant time on the total page load, but in trying the following change has no significant performance change

(defn- add-children!
  [this [child-cell & _ :as kids]]
  ;;vflatten+map in single pass
  (vflattenf #(when-let [x (->node %)]
                  (-append-child! this x))
               kids)
  #_(doseq [x (vflatten kids)]
    (when-let [x (->node x)]
      (-append-child! this x))))

2018-06-27T17:22:14.000250Z

(take the "no significant performance gain" with a grain of salt, i just started attempting to profile hoplon. Also a lot of this depends what is the typical use case of hoplon is to optimize for)

2018-06-27T17:24:14.000040Z

for example i've found that when i use hoplon, most the time elements just have 1-5 children, and any sort of nesting of vectors of children is fairly rare

2018-06-27T17:26:46.000501Z

was saying to flyboarder yesterday that I started looking at "average number of children per element" found in the wild with this js snippet in chrome dev tools:

var all = document.body.getElementsByTagName("*");
var n = 0
for (var i=0, max=all.length; i < max; i++) {
	n += all[i].children.length
}
n / all.length
and it's almost always extremely close to 1

2018-06-27T17:42:21.000191Z

I see, profile-directed is definitely the way to go

2018-06-27T17:42:48.000442Z

I'll stop suggesting pointless work for you šŸ˜„

2018-06-27T17:49:28.000446Z

haha

2018-06-27T17:50:36.000439Z

actually i have one more maybe-pointless item to suggest lol

2018-06-27T17:50:51.000467Z

are you familiar with compiler-macros?

2018-06-27T17:50:56.000028Z

like, the concept?

2018-06-27T17:51:57.000515Z

you mean like macros that are sort of little compilers?

2018-06-27T17:52:24.000120Z

well macros are little compilers basically, so yeah, but this is a particular kind of macro application semantic that cljs supports (i believe. it did originally)

2018-06-27T17:52:59.000313Z

the idea with them is that for any function not passed by value or apply'd, its arguments are known at compile-time

2018-06-27T17:53:22.000611Z

for example (+ 1 2 3) - at compile time we know that + is being called with 3 arguments

2018-06-27T17:53:41.000245Z

so there's a mechanism to set up a function to be called by the compiler when it encounters a call like this

2018-06-27T17:54:06.000491Z

which makes + have a kind of dual-nature - when its called inline the compiler macro associated with it (if any) has an opportunity to produce code in place of the expression

2018-06-27T17:54:21.000175Z

but it's also a function at runtime so you can e.g. (reduce + '(1 2 3))

2018-06-27T17:55:12.000414Z

so if you have a compiler macro for + and it gets an arglist like '(1 2 3), it might see the arguments are constant and do the addition at compile time and return 6 as a substitute for (+ 1 2 3)

2018-06-27T17:55:32.000512Z

the direction i'm going with this is, a lot of any given hoplon app's markup is static

2018-06-27T17:55:57.000056Z

and so in many cases it might not be necessary to represent children at runtime at all. at compile-time turn child arguments into the code to appendchild

2018-06-27T17:56:38.000445Z

theory being this would speed initial app load

2018-06-27T17:57:03.000458Z

oh yeah, that is an interesting idea

flyboarder 2018-06-27T18:10:37.000101Z

@alandipert šŸ¤Æ

2018-06-27T18:35:01.000080Z

ok sweet, yeah, according to mfikes in #clojurescript the way to do it is to make a macro the same name as the function

2018-06-27T18:35:15.000060Z

and the compiler automatically uses the macro when it can

2018-06-27T18:36:02.000068Z

so for us that would mean something like auto-generating a bunch of html ctor macros in hoplon.core on the clj side

2018-06-27T18:41:42.000048Z

so that would basically allow elements (when they are static) to just expand into big chains of just .createElements and appendChild without any other in between stuff? or is there something more to it?

2018-06-27T18:45:03.000204Z

that's what i'm thinking, yeah

2018-06-27T18:45:54.000198Z

cool

2018-06-27T19:49:50.000038Z

@hiskennyness +1 ratoms, very cellular feel

2018-06-27T19:50:04.000048Z

(i've only fiddle with demos)

flyboarder 2018-06-27T19:57:04.000024Z

I think that will work well because we only need runtime elements for cells, ie templating

flyboarder 2018-06-27T20:08:37.000124Z

But that means we need a macro for every element tag?

flyboarder 2018-06-27T20:11:47.000415Z

But I wonder if we can have the defelem generate the macros for custom elements too

2018-06-27T20:22:49.000092Z

yeah i think so

2018-06-27T20:23:01.000040Z

well, maybe

2018-06-27T20:56:44.000017Z

ok i think i might have overestimated the work involved in doing the js array internals yesterday, I got a very rough version working and it seems 100x faster already slightly_smiling_face edit: no not nearly that much faster

flyboarder 2018-06-27T21:46:35.000168Z

Cool, Iā€™m stoked to see more improvements to the core

2018-06-27T22:15:34.000138Z

it seems closer to 5% faster with the stress test i've been using after using an array for the storage of the children

2018-06-27T22:17:03.000212Z

that's an additional 5% after the ~7% speed improvement over the master branch with the new child-vec and vflatten fns i have

2018-06-27T22:17:22.000189Z

if it can keep compounding like this it'll be nice šŸ™‚

2018-06-27T22:37:02.000181Z

those are awesome gains, thanks @jjttjj