I’m using spec to validate updates before saving to a DB - basically updated/created entities have to match the schema for their type before I attempt the actual db write. I found that this validation stage was slow, and made some changes to the specs and saw huge perf gains. I’m wondering whether there’s any guidance online for writing efficient specs, or whether anyone has any tips.
As an example, here’s the change I made, which in hindsight is pretty obvious.
;; Domain entities have an :entity/type key indicating their type. ;; It's a survey-building app, so the types are :entity.type/question, ;; :entity.type/survey, etc. (defn constrain-type [t] (fn [x] (= (:entity/type x) t))) ;; Initial version (s/def ::question (s/and (s/keys :req [...]) (constrain-type :entity.type/question))) (s/def ::survey-content (s/or :q ::question :p ::page)) ;; Way faster version (s/def ::question (s/and ;; next two lines are swapped from initial version (constrain-type :entity.type/question) (s/keys :req [...])))
It makes sense that the second version is faster; ::question and ::page have similar specs, so putting
constrain-type first makes it so we can rule out non-matches faster.