   (let [cache (make-array (count plan))
         result (transient #{})]
     (run-plan plan cache kn)
-    (doseq [assert-ix assert-ixes
-            fact (aget cache assert-ix)]
-      (conj!! result fact))
-    (doseq [retract-ix retract-ixes
-            fact (aget cache retract-ix)]
-      (disj!! result fact))
+    (console-time "query asserts" profile?
+                  (doseq [assert-ix assert-ixes
+                          fact (aget cache assert-ix)]
+                    (conj!! result fact)))
+    (console-time "query retracts" profile?
+                  (doseq [retract-ix retract-ixes
+                          fact (aget cache retract-ix)]
+                    (disj!! result fact)))
     (persistent! result)))
 
 (comment

  (-s vars fn)
  )

;; TODO
;; query optimisation (starting with clause sorting)
;; aggregates (conj? sorting?)

  [(dec (alength plan)) (:shape node)])

(defn run-plan [plan cache kn]
  (console-time (str "plan") profile?
                (dotimes [i (count plan)]
                  (console-time (pr-str (type (nth plan i))) profile?
                                (aset cache i (run-node (nth plan i) cache kn))))))

(comment
  (let [kn (->Knowledge nil nil nil #{{:a 1 :b 2} {:a 2 :b 3} {:c 1 :b 2} {:c 2 :d 4}})
