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