performance increases

memoize construction of ranges, and use transient/mutable
Java collections for internal collection state
This commit is contained in:
2026-01-13 21:01:46 -06:00
parent df24a84908
commit 9ffa5d1b97
3 changed files with 42 additions and 37 deletions

View File

@@ -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)

View File

@@ -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)
(case boundary-type
:start (do
(when-not (seq @stack)
(vreset! start (:value input)))
(vswap! stack (fnil conj []) input)
(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
@@ -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
(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

View File

@@ -31,10 +31,12 @@
(toString [_this]
(str start ".." end)))
(defn int-range-inclusive [start end]
(defn- int-range-inclusive* [start end]
(assert (<= start end) (str "start : " start "; end: " end))
(->IntInclusiveDiscreteValueRange start end))
(def int-range-inclusive (memoize int-range-inclusive*))
(defmethod range/->discrete-value-range :int-range-inclusive [_ start end]
(int-range-inclusive start end))