Clojure

Unroll constantly to improve performance of multi-arity calls

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test
  • Approval:
    Prescreened

Description

This was found to be a hot spot when testing some Specter use cases.

Review of common uses of constantly shows that the arity 1 case is the most common use of `constantly` in the wild, so only unrolled to two arguments.

Perf test:

(use 'criterium.core)
(def f (constantly 1))
(bench (dotimes [_ 1000] (f)))
(bench (dotimes [_ 1000] (f 1)))
(bench (dotimes [_ 1000] (f 1 2)))

;; Results:
;; Arity Before         After
;; 0     611.455589 ns  607.800747 ns    (no change was expected)
;; 1     3.098828 µs    611.116510 ns    (~5x improvement)
;; 2     3.508726 µs    620.415032 ns    (~5x improvement)

Patch: 0001-CLJ-2228-Improve-performance-of-constantly.patch

Prescreened by: Alex Miller

Activity

Hide
Alex Miller added a comment -

I want to call out to our workflow diagram at https://dev.clojure.org/display/community/JIRA+workflow for process here. I've triaged this, but it's unlikely to be reviewed for the next release at this point unless it's been prescreened, and that requires a patch. So it would be helpful if you could:

  • mention your use case where this made a difference (Specter)
  • attach a patch
  • include the benchmarks in the ticket description

One question I have is how many arities to unroll. 10 seems like a lot? My guess is that up to 2 or 3 args would cover 90+% of cases but could poke around in https://crossclj.info/fun/clojure.core/constantly.html or do some other research to get an idea.

Show
Alex Miller added a comment - I want to call out to our workflow diagram at https://dev.clojure.org/display/community/JIRA+workflow for process here. I've triaged this, but it's unlikely to be reviewed for the next release at this point unless it's been prescreened, and that requires a patch. So it would be helpful if you could:
  • mention your use case where this made a difference (Specter)
  • attach a patch
  • include the benchmarks in the ticket description
One question I have is how many arities to unroll. 10 seems like a lot? My guess is that up to 2 or 3 args would cover 90+% of cases but could poke around in https://crossclj.info/fun/clojure.core/constantly.html or do some other research to get an idea.
Hide
Alex Miller added a comment -

What is the max arity for constantly you encounter in Specter?

Show
Alex Miller added a comment - What is the max arity for constantly you encounter in Specter?
Hide
Alex Miller added a comment -

I did some poking around and I suspect arity 1 is the 98% use case and arity 0 making up most of the rest. I failed to actually find an example of any arity >1 although I'm sure there are a few of them out there. I think unrolling to arity 2 would be more than sufficient.

Show
Alex Miller added a comment - I did some poking around and I suspect arity 1 is the 98% use case and arity 0 making up most of the rest. I failed to actually find an example of any arity >1 although I'm sure there are a few of them out there. I think unrolling to arity 2 would be more than sufficient.
Hide
Nathan Marz added a comment -

Specter uses constantly for arity 1, so this patch is sufficient for Specter.

Show
Nathan Marz added a comment - Specter uses constantly for arity 1, so this patch is sufficient for Specter.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated: