performance increases
memoize construction of ranges, and use transient/mutable Java collections for internal collection state
This commit is contained in:
@@ -24,13 +24,13 @@
|
||||
(union [this other]
|
||||
(when-not (.isConnected this other)
|
||||
(throw (ex-info "Cannot union non-connecting ranges" {})))
|
||||
(.union this other))
|
||||
(before [^LocalDateRange this ^LocalDate x]
|
||||
(.isBefore this x))
|
||||
(after [this ^LocalDate x]
|
||||
(.isAfter (.getEndInclusive this) x)))
|
||||
(.union this other)))
|
||||
|
||||
(def ^:private closed-local-date-range
|
||||
(memoize (fn [start end]
|
||||
(LocalDateRange/ofClosed start end))))
|
||||
|
||||
(defmethod range/->discrete-value-range :local-date-range [_ start end]
|
||||
(LocalDateRange/ofClosed start end))
|
||||
(closed-local-date-range start end))
|
||||
|
||||
(def difference range/difference)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
that before/after values against other values that the range
|
||||
is over.
|
||||
"
|
||||
(abuts [this ^DiscreteValueRange other])
|
||||
(abuts [this other])
|
||||
(value-before [this])
|
||||
(value-after [this])
|
||||
(start [this])
|
||||
@@ -34,6 +34,18 @@
|
||||
(range-type [this])
|
||||
(union [this other]))
|
||||
|
||||
(defn ->range-boundaries* [range]
|
||||
[{:value (start range)
|
||||
:boundary-type :start
|
||||
:type (range-type range)
|
||||
:prev-value (value-before range)}
|
||||
{:value (end range)
|
||||
:boundary-type :end
|
||||
:type (range-type range)
|
||||
:next-value (value-after range)}])
|
||||
|
||||
(def ->range-boundaries (memoize ->range-boundaries*))
|
||||
|
||||
(defn- ordered-range-values
|
||||
"Builds an ordered list or 'fenceposts' for the start and end
|
||||
of all given ranges, to prepare to produces a consolidated
|
||||
@@ -48,15 +60,7 @@
|
||||
any intermediate matching starts/stops."
|
||||
[ranges]
|
||||
(->> ranges
|
||||
(mapcat (fn [range]
|
||||
[{:value (start range)
|
||||
:boundary-type :start
|
||||
:type (range-type range)
|
||||
:prev-value (value-before range)}
|
||||
{:value (end range)
|
||||
:boundary-type :end
|
||||
:type (range-type range)
|
||||
:next-value (value-after range)}]))
|
||||
(mapcat ->range-boundaries)
|
||||
(sort-by (juxt :value (comp {:start 0 :end 1} :boundary-type)))))
|
||||
|
||||
(defmulti ->discrete-value-range (fn [range-type _start _end]
|
||||
@@ -77,25 +81,25 @@
|
||||
end pairs encountered between the new start and end values."
|
||||
[]
|
||||
(fn [xf]
|
||||
(let [stack (volatile! [])
|
||||
(let [stack (java.util.Stack.)
|
||||
start (volatile! nil)]
|
||||
(fn
|
||||
([] (xf))
|
||||
([result] (xf result))
|
||||
([result input]
|
||||
([result {:keys [boundary-type value type] :as input}]
|
||||
(if (reduced? input)
|
||||
result
|
||||
(case (:boundary-type input)
|
||||
:start (do
|
||||
(when-not (seq @stack)
|
||||
(vreset! start (:value input)))
|
||||
(vswap! stack (fnil conj []) input)
|
||||
result)
|
||||
(case boundary-type
|
||||
:start (do
|
||||
(when (.empty stack)
|
||||
(vreset! start value))
|
||||
(.push stack input)
|
||||
result)
|
||||
:end (do
|
||||
(vswap! stack pop)
|
||||
(if (seq @stack)
|
||||
(.pop stack)
|
||||
(if (not (.empty stack))
|
||||
result
|
||||
(xf result (->discrete-value-range (:type input) @start (:value input))))))))))))
|
||||
(xf result (->discrete-value-range type @start value)))))))))))
|
||||
|
||||
(defn- combine-abutting-ranges
|
||||
"transducer to join ranges where the start and end of two ranges are consective
|
||||
@@ -124,9 +128,9 @@
|
||||
(vreset! prev item)
|
||||
result)
|
||||
|
||||
:else (let [item @prev]
|
||||
(vreset! prev input)
|
||||
(xf result item))))))))
|
||||
:else (let [item @prev]
|
||||
(vreset! prev input)
|
||||
(xf result item))))))))
|
||||
|
||||
(def consolidate-ranges-xf
|
||||
(comp
|
||||
@@ -138,18 +142,17 @@
|
||||
|
||||
(defn walk-range-boundaries [range-boundary-items]
|
||||
(let [close-working-range (fn [range-type start end ranges]
|
||||
(conj ranges (->discrete-value-range range-type
|
||||
start
|
||||
end)))]
|
||||
|
||||
(conj! ranges (->discrete-value-range range-type
|
||||
start
|
||||
end)))]
|
||||
(loop [[boundary-item & boundary-items] range-boundary-items
|
||||
in-filter-range nil
|
||||
in-source-range nil
|
||||
ranges #{}
|
||||
ranges (transient #{})
|
||||
close-fn nil]
|
||||
(match [boundary-item]
|
||||
[nil]
|
||||
ranges
|
||||
(persistent! ranges)
|
||||
|
||||
[{:boundary-type :start
|
||||
:range-source-type :source-range
|
||||
|
||||
Reference in New Issue
Block a user