-
-
Notifications
You must be signed in to change notification settings - Fork 95
/
query_stats.cljc
84 lines (77 loc) · 3.09 KB
/
query_stats.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
(ns datahike.query-stats
(:require [clojure.set :as set]
[datahike.tools :as dt]))
(defn round [precision x]
#?(:clj (with-precision precision x)
:cljs (let [y (Math/pow 10 precision)]
(/ (.round js/Math (* y x)) y))))
(defn get-stats [context]
{:rels (mapv (fn [rel] {:rows (count (:tuples rel))
:bound (set (keys (:attrs rel)))})
(:rels context))})
(defn update-ctx-with-stats
"update-fn must expect [context] as argument"
[context clause update-fn]
(if (:stats context)
(let [{:keys [res t]} (dt/timed #(update-fn context))
clause-stats (merge (get-stats res)
{:clause clause
:t t}
(:tmp-stats res))]
(-> res
(update :stats conj clause-stats)
(dissoc :tmp-stats)))
(update-fn context)))
(defn extend-stat
"Adds summarized row counts, bindings and clause time for convenience"
[{:keys [branches rels] :as stat}]
(assoc stat
:id (subs (str (abs (hash stat))) 0 6)
:t-branches (reduce #(+ %1 (:t %2)) 0.0 branches)
:rel-count (count rels)
:rows (reduce #(+ %1 (:rows %2)) 0 rels)
:bound (reduce #(set/union %1 (:bound %2)) #{} rels)
:branches (mapv extend-stat branches)))
(defn get-stat-diffs [parent-node prev-node {:keys [t t-branches rows bound] :as node}]
(let [extend-and-branches (fn [branches]
(mapv (partial get-stat-diffs node)
(cons prev-node branches)
branches))
extend-or-branches (fn [branches]
(mapv (partial get-stat-diffs node prev-node) branches))]
(-> node
(dissoc :rows :bound)
(assoc :prev (:id prev-node)
:parent (:id parent-node)
:t-diff (round 6 (- t t-branches))
:rows-in (:rows prev-node)
:rows-out rows
:rows-diff (- rows (:rows prev-node))
:bound-in (:bound prev-node)
:bound-out bound
:bound-diff (set/difference bound (:bound prev-node)))
(update :branches (case (:type node)
:and extend-and-branches
:or extend-or-branches
:or-join extend-or-branches
:rule extend-or-branches
:solve extend-and-branches
identity)))))
(defn extend-stats [stats]
(let [extended (map extend-stat stats)
root {:rows 0 :bound (set []) :id "_root_"}]
(mapv (partial get-stat-diffs root)
(cons root extended)
extended)))
(defn stats-table
([stats]
(stats-table stats [:id :prev :parent :clause :type
:rows-in :rows-diff :bound-in :bound-diff
:t :t-diff :clauses]))
([stats cols]
(->> stats
extend-stats
(hash-map :branches)
(tree-seq map? :branches)
rest
(map (apply juxt cols)))))