Optimize dash-to-prop-name & capitalize fns
This PR optimizes string manipulation code in reagent.impl.util/dash-to-prop-name and reagent.impl.util/capitalize which results in ~34% speedup when interpreting Hiccup, according to synthetic benchmark added here.
I suspect similar optimizations could be done in other parts of code base, but this can be done in separate PRs.
So, I did some testing with this:
- Currently this doesn't work as destructuring will return
partsas Seq, not Array array-reduceis private in cljs.core- I can't see any performance different with Firefox or Chrome here, 5000ms with the old function and the new in both browsers.
- Test case contains lots of hiccup tags with classes, but this change doesn't affect tag name parsing, which might explain why I don't see change.
I tested version like this, where destructuring is not used so split result is kept as Array:
(defn dash-to-prop-name [dashed]
(if (string? dashed)
dashed
(let [name-str (name dashed)
parts (.split name-str #"-")
start (aget parts 0)]
(cond
(contains? dont-camel-case start) name-str
(> (.-length parts) 1)
(-> (array-reduce
parts
(fn [a p]
(.push a (capitalize p))
a)
#js [start]
1)
(.join ""))
:else start))))
I think we can use normal reduce here and it will fall into array-reduce when applied to js/Array. Perf difference should be noticeable for Hiccup with lots of attributes and inline styles.
Yes, reduce is probably fine. Though it doesn't directly call arrray-reduce. When destructuring is used to get start and parts, parts will be ArrayChunk which has it's own IReduce implementation using array-reduce and offset.
I'll look more into this after getting 0.9 finally out.
Probably benchmarking the dash-to-prop-name alone, preferably with Benchmark.js, should provide more information about this change.
Pushed an update to avoid implicit conversion to a seq when destructuring js/array
@Deraen Is there anything blocking this PR from getting merged?
I think I was unsure of the performance improvements last I tried to benchmark this.
Probably benchmarking the dash-to-prop-name alone, preferably with Benchmark.js, should provide more information about this change.