Skip to content

Commit feb9fce

Browse files
committed
restored fast init-db
1 parent 2f7a4b3 commit feb9fce

8 files changed

Lines changed: 144 additions & 37 deletions

File tree

deps.edn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
:dev {
1515
:extra-paths ["dev" "target/classes"]
1616
:extra-deps {
17+
org.clojure/clojurescript {:mvn/version "1.10.516"}
1718
org.clojure/tools.namespace {:mvn/version "0.2.11"}
1819
}
1920
}

src-java/datascript/ASortedSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import clojure.lang.*;
55

66
@SuppressWarnings("unchecked")
7-
public abstract class ASortedSet implements IObj, Counted, IPersistentSet, ILookup, Iterable, Set, java.io.Serializable, IHashEq {
7+
public abstract class ASortedSet extends AFn implements IObj, Counted, IPersistentSet, ILookup, Iterable, Set, java.io.Serializable, IHashEq {
88
int _hash;
99
int _hasheq;
1010
final IPersistentMap _meta;

src-java/datascript/SortedSet.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ public class SortedSet extends ASortedSet implements IEditableCollection, ITrans
99
static Leaf[] EARLY_EXIT = new Leaf[0],
1010
UNCHANGED = new Leaf[0];
1111

12-
static int MIN_LEN = 32, MAX_LEN = 64, EXTRA_LEN = 8;
12+
public static int MIN_LEN = 32, MAX_LEN = 64, EXTRA_LEN = 8;
1313

1414
public static final SortedSet EMPTY = new SortedSet();
1515

16-
static class Edit {
16+
public static class Edit {
1717
public volatile boolean _value = false;
18-
Edit(boolean value) { _value = value; }
18+
public Edit(boolean value) { _value = value; }
1919
public boolean editable() { return _value; }
2020
public void setEditable(boolean value) { _value = value; }
2121
}
@@ -38,7 +38,7 @@ public SortedSet(IPersistentMap meta, Comparator cmp) {
3838
_count = 0;
3939
}
4040

41-
SortedSet(IPersistentMap meta, Comparator cmp, Leaf root, int count, Edit edit) {
41+
public SortedSet(IPersistentMap meta, Comparator cmp, Leaf root, int count, Edit edit) {
4242
super(meta, cmp);
4343
_root = root;
4444
_count = count;
@@ -252,18 +252,18 @@ public Iterator iterator() {
252252

253253
// ===== LEAF =====
254254

255-
static class Leaf {
255+
public static class Leaf {
256256
final Object[] _keys;
257257
int _len;
258258
final Edit _edit;
259259

260-
Leaf(Object[] keys, int len, Edit edit) {
260+
public Leaf(Object[] keys, int len, Edit edit) {
261261
_keys = keys;
262262
_len = len;
263263
_edit = edit;
264264
}
265265

266-
Object maxKey() {
266+
public Object maxKey() {
267267
return _keys[_len-1];
268268
}
269269

@@ -517,10 +517,10 @@ public String str(int lvl) {
517517

518518
// ===== NODE =====
519519

520-
static class Node extends Leaf {
520+
public static class Node extends Leaf {
521521
final Leaf[] _children;
522522

523-
Node(Object[] keys, Leaf[] children, int len, Edit edit) {
523+
public Node(Object[] keys, Leaf[] children, int len, Edit edit) {
524524
super(keys, len, edit);
525525
_children = children;
526526
}

src-java/datascript/Stitch.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datascript;
22

33
import java.util.*;
4+
import clojure.lang.*;
45

56
public class Stitch<T> {
67

@@ -9,6 +10,25 @@ public static <T> T[] copy(T[] src, int from, int to, T[] target, int offset) {
910
return target;
1011
}
1112

13+
public static Object indexedToArray(Class type, Indexed coll, int from, int to) {
14+
int len = to - from;
15+
Object ret = java.lang.reflect.Array.newInstance(type, len);
16+
for (int i = 0; i < len; ++i)
17+
java.lang.reflect.Array.set(ret, i, coll.nth(i+from));
18+
return ret;
19+
}
20+
21+
public static int distinct(Comparator<Object> cmp, Object[] arr) {
22+
int to = 0;
23+
for (int idx = 1; idx < arr.length; ++idx) {
24+
if (cmp.compare(arr[idx], arr[to]) != 0) {
25+
++to;
26+
if (to != idx) arr[to] = arr[idx];
27+
}
28+
}
29+
return to + 1;
30+
}
31+
1232
T[] target;
1333
int offset;
1434

src/datascript/arrays.cljc

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,29 +73,47 @@
7373
(System/arraycopy ^{:tag "[[Ljava.lang.Object;"} b 0 res al bl)
7474
res)))
7575

76-
(defn amap [f arr]
77-
#?(:cljs (.map arr f)
78-
:clj (clojure.core/amap ^{:tag "[[Ljava.lang.Object;"} arr i res (f (aget arr i)))))
76+
#?(:cljs
77+
(defn amap [f arr]
78+
(.map arr f))
79+
:clj
80+
(defn amap
81+
([f arr]
82+
(amap f Object arr))
83+
([f type arr]
84+
(let [res (clojure.core/make-array type (alength arr))]
85+
(dotimes [i (alength arr)]
86+
(aset res i (f (aget arr i))))
87+
res))))
7988

8089
(defn asort [arr cmp]
8190
#?(:cljs (.sort arr cmp)
82-
:clj (doto arr (java.util.Arrays/sort cmp))))
91+
:clj (doto arr (Arrays/parallelSort cmp))))
8392

84-
#?(:cljs (defn ^boolean array? [x]
85-
(if (identical? *target* "nodejs")
86-
(.isArray js/Array x)
87-
(instance? js/Array x)))
88-
:clj (defn array? [^Object x] (-> x .getClass .isArray)))
93+
#?(:cljs
94+
(defn ^boolean array? [x]
95+
(if (identical? *target* "nodejs")
96+
(.isArray js/Array x)
97+
(instance? js/Array x)))
98+
:clj
99+
(defn array? [^Object x]
100+
(-> x .getClass .isArray)))
89101

90102
#?(:clj
91-
(defmacro alast [arr]
92-
`(let [arr# ~arr]
93-
(aget arr# (dec (alength arr#))))))
103+
(defmacro alast [arr]
104+
`(let [arr# ~arr]
105+
(aget arr# (dec (alength arr#))))))
94106

95107
#?(:clj
96-
(defmacro half [x]
97-
`(unsigned-bit-shift-right ~x 1)))
108+
(defmacro half [x]
109+
`(unsigned-bit-shift-right ~x 1)))
98110

99111
#?(:clj
100-
(defmacro not== [x y]
101-
`(not (== ~x ~y))))
112+
(defmacro not== [x y]
113+
`(not (== ~x ~y))))
114+
115+
#?(:clj
116+
(def array-type
117+
(memoize
118+
(fn [type]
119+
(.getClass ^Object (java.lang.reflect.Array/newInstance ^Class type 0))))))

src/datascript/btset.clj

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
(ns ^{:no-doc true
22
:author "Nikita Prokopov"}
33
datascript.btset
4+
(:require
5+
[datascript.arrays :as da])
46
(:import
5-
[java.util Comparator]
6-
[datascript SortedSet]))
7+
[java.util Comparator Arrays]
8+
[datascript SortedSet SortedSet$Leaf SortedSet$Node SortedSet$Edit Stitch]))
9+
710

811
(defn btset-conj [set key cmp]
912
(.cons ^SortedSet set key cmp))
1013

14+
1115
(defn btset-disj [set key cmp]
1216
(.disjoin ^SortedSet set key cmp))
1317

18+
1419
(defn slice
1520
"`(slice set key)` returns iterator that contains all elements equal to the key.
1621
`(slice set from to)` returns iterator for all Xs where from <= X <= to.
@@ -22,6 +27,7 @@
2227
([set from to cmp]
2328
(.slice ^SortedSet set from to ^Comparator cmp)))
2429

30+
2531
(defn rslice
2632
"`(rslice set from to)` returns backwards iterator for all Xs where from <= X <= to.
2733
`(rslice set from nil)` returns backwards iterator for all Xs where X <= from."
@@ -30,12 +36,69 @@
3036
([set from to cmp]
3137
(.rslice ^SortedSet set from to ^Comparator cmp)))
3238

39+
40+
(defn- array-from-indexed [coll type from to]
41+
(cond
42+
(instance? clojure.lang.Indexed coll)
43+
(Stitch/indexedToArray type coll from to)
44+
45+
(da/array? coll)
46+
(Arrays/copyOfRange coll from to (da/array-type type))))
47+
48+
49+
(defn- split
50+
([coll to type avg max]
51+
(persistent! (split (transient []) 0 coll to type avg max)))
52+
([res from coll to type avg max]
53+
(let [len (- to from)]
54+
(cond
55+
(== 0 len)
56+
res
57+
58+
(>= len (* 2 avg))
59+
(recur (conj! res (array-from-indexed coll type from (+ from avg))) (+ from avg) coll to type avg max)
60+
61+
(<= len max)
62+
(conj! res (array-from-indexed coll type from to))
63+
64+
:else
65+
(-> res
66+
(conj! (array-from-indexed coll type from (+ from (quot len 2))))
67+
(conj! (array-from-indexed coll type (+ from (quot len 2)) to)))))))
68+
69+
70+
(defn from-sorted-array
71+
([cmp keys]
72+
(from-sorted-array cmp keys (da/alength keys)))
73+
([cmp keys len]
74+
(let [max SortedSet/MAX_LEN
75+
avg (quot (+ SortedSet/MIN_LEN max) 2)
76+
edit (SortedSet$Edit. false)
77+
->Leaf (fn [keys]
78+
(SortedSet$Leaf. keys (count keys) edit))
79+
->Node (fn [children]
80+
(SortedSet$Node.
81+
(da/amap #(.maxKey ^SortedSet$Leaf %) Object children)
82+
children (count children) edit))]
83+
(loop [nodes (mapv ->Leaf (split keys len Object avg max))]
84+
(case (count nodes)
85+
0 (SortedSet. cmp)
86+
1 (SortedSet. {} cmp (first nodes) len edit)
87+
(recur (mapv ->Node (split nodes (count nodes) SortedSet$Leaf avg max))))))))
88+
89+
90+
(defn ctor [^Comparator cmp keys]
91+
(let [arr (to-array keys)
92+
_ (da/asort arr cmp)
93+
len (Stitch/distinct cmp arr)]
94+
(from-sorted-array cmp arr len)))
95+
96+
3397
(defn btset-by
3498
([cmp] (SortedSet. ^Comparator cmp))
35-
([cmp & keys]
36-
(into (btset-by cmp) keys)))
99+
([cmp & keys] (ctor cmp keys)))
100+
37101

38102
(defn btset
39103
([] (SortedSet.))
40-
([& keys]
41-
(into (btset) keys)))
104+
([& keys] (ctor compare keys)))

src/datascript/btset.cljs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,10 +887,10 @@
887887
;; public interface
888888

889889
(defn -btset-from-sorted-arr [arr cmp]
890-
(let [leafs (->> arr
890+
(let [leaves (->> arr
891891
(arr-partition-approx min-len max-len)
892892
(arr-map-inplace #(Leaf. %)))]
893-
(loop [current-level leafs
893+
(loop [current-level leaves
894894
shift 0]
895895
(case (count current-level)
896896
0 (BTSet. (Leaf. (da/array)) 0 0 cmp nil uninitialized-hash)

src/datascript/db.cljc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,10 +656,15 @@
656656
avet (btset/-btset-from-sorted-arr avet-datoms cmp-datoms-avet)
657657
max-eid (init-max-eid eavt)]
658658
:clj
659-
[eavt (apply btset/btset-by cmp-datoms-eavt datoms)
660-
aevt (apply btset/btset-by cmp-datoms-aevt datoms)
659+
[arr (to-array datoms)
660+
_ (da/asort arr cmp-datoms-eavt-quick)
661+
eavt (btset/from-sorted-array cmp-datoms-eavt arr)
662+
_ (da/asort arr cmp-datoms-aevt-quick)
663+
aevt (btset/from-sorted-array cmp-datoms-aevt arr)
661664
avet-datoms (filter (fn [^Datom d] (contains? indexed (.-a d))) datoms)
662-
avet (apply btset/btset-by cmp-datoms-avet avet-datoms)
665+
avet-arr (to-array avet-datoms)
666+
_ (da/asort avet-arr cmp-datoms-avet-quick)
667+
avet (btset/from-sorted-array cmp-datoms-avet avet-arr)
663668
max-eid (init-max-eid eavt)])
664669
max-tx (transduce (map (fn [^Datom d] (.-tx d))) max tx0 eavt)]
665670
(map->DB {

0 commit comments

Comments
 (0)