-
-
Save hiiamboris/4da1bccf63f4506b412977c1673c723c to your computer and use it in GitHub Desktop.
Red [title: "reactivity benchmark" needs: view] ;) run as `red --cli ...` to eliminate GUI console influence! | |
do https://gitlab.com/hiiamboris/red-mezz-warehouse/-/raw/master/clock.red | |
do-unseen: function [code [block!]] [ | |
old: system/view/auto-sync? | |
system/view/auto-sync?: no | |
do code | |
system/view/auto-sync?: old | |
] | |
extend system/view/VID/styles [ | |
text1: [ | |
template: [type: 'text size: 80x25] | |
init: [ ;) baseline: creates a function, executes, doesn't use it | |
f: func [f _] [ | |
[f/data f/offset f/size] | |
f/text: "text" | |
] | |
f face face | |
] | |
] | |
text2: [ | |
template: [type: 'text size: 80x25] | |
init: [ | |
react/link func [f _] [ | |
[f/data f/offset f/size] ;) define reactive sources (3 sources = 3 reactions) | |
f/text: "text" | |
] [face face] | |
] | |
] | |
] | |
view/no-wait [p: panel []] | |
recycle/off | |
print "=== BASELINE (VIEW ONLY) ===" | |
print "" | |
print "CREATING 1000 FACES x5" | |
loop 5 [clock [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]] | |
print "SHOWING 1000 FACES" | |
print ["p/pane:" length? p/pane "faces"] | |
clock [show p] | |
clear p/pane | |
clock [recycle] | |
print "" | |
print "=== WITH REACTIVITY ===" | |
print "" | |
print "CREATING 1000 FACES & 3000 REACTIONS x5 (A TOTAL OF 15000 REACTIONS)" | |
loop 5 [clock [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]] | |
print "SHOWING 1000 FACES & DESTROYING 12000 REACTIONS" | |
print ["p/pane:" length? p/pane "faces"] | |
print ["relations count:" (length? system/reactivity/relations) / 4] | |
clock [show p] | |
print ["relations count:" (length? system/reactivity/relations) / 4] | |
clear p/pane | |
clock [clear-reactions] | |
clock [recycle] | |
unview do-events/no-wait | |
print "" | |
print "=== ONLY REACTIVITY (NO VIEW) ===" | |
print "" | |
print "CREATING 1000 REACTORS x5" | |
b: [[][][][][]] | |
repeat i 5 [clock compose/deep [clear pick b (i) loop 1000 [append pick b (i) reactor [x: 10 y: 2 t: 0 re: copy/deep [self/t: s/s * self/x + self/y]]]]] | |
print "CREATING 15000 REACTIONS" | |
s: reactor [s: 1] | |
repeat i 5 [clock compose [foreach r pick b (i) [react/later r/re]]] | |
print ["relations count:" (length? system/reactivity/relations) / 4] | |
?? b/1/1/t ?? b/2/2/t | |
print "FIRING 15000 REACTIONS" | |
clock [s/s: 2] | |
?? b/1/1/t ?? b/2/2/t | |
print "DESTROYING 15000 REACTIONS" | |
repeat i 5 [clock compose [foreach r pick b (i) [react/unlink r/re 'all]]] | |
print ["relations count:" (length? system/reactivity/relations) / 4] | |
clock [recycle] | |
print "" | |
print "=== ONLY REACTIVITY AND OBJECTS MAINLY UNIQUE ===" | |
print "" | |
print "CREATING 1000 REACTORS x5" | |
b: [[][][][][]] | |
s: reactor [x: 10 y: 2 t: 0 re: [this/t: that/x + that/y + that/t / 10]] | |
repeat i 5 [clock compose/deep [clear pick b (i) loop 1000 [append pick b (i) make s [re: copy/deep re]]]] | |
print "CREATING 15000 REACTIONS" | |
prev: s | |
repeat i 5 [clock compose [foreach r pick b (i) [react/link/later r/re: func [this that] r/re [r prev] prev: r]]] | |
print ["relations count:" (length? system/reactivity/relations) / 4] | |
?? b/1/1/t ?? b/2/2/t | |
print "FIRING 15000 REACTIONS" | |
clock [s/t: 1] | |
?? b/1/1/t ?? b/2/2/t | |
print "DESTROYING 15000 REACTIONS" | |
repeat i 5 [clock compose [foreach r pick b (i) [react/unlink :r/re 'all]]] | |
; print ["relations count:" (length? system/reactivity/relations) / 4] | |
clock [recycle] |
hiiamboris
commented
May 24, 2020
With relations: make hash! 1000
instead of relations: make block! 1000
- slower!
=== BASELINE (VIEW ONLY) ===
CREATING 1000 FACES x5
230 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
227 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
225 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
227 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
226 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
SHOWING 1000 FACES
p/pane: 1000 faces
2113 ms [show p]
496 ms [recycle]
=== WITH REACTIVITY ===
CREATING 1000 FACES & 3000 REACTIONS x5 (A TOTAL OF 15000 REACTIONS)
743 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
1424 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
2307 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
2646 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
4717 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
SHOWING 1000 FACES & DESTROYING 12000 REACTIONS
p/pane: 1000 faces
relations count: 15000
41036 ms [show p]
relations count: 3000
548 ms [recycle]
I hacked the code to use a var for the count.
do https://gitlab.com/hiiamboris/red-mezz-warehouse/-/raw/master/clock.red
do-unseen: function [code [block!]] [
old: system/view/auto-sync?
system/view/auto-sync?: no
do code
system/view/auto-sync?: old
]
extend system/view/VID/styles [
text1: [
template: [type: 'text size: 80x25]
init: [ ;) baseline: creates a function, executes, doesn't use it
f: func [f _] [
[f/data f/offset f/size]
f/text: "text"
]
f face face
]
]
text2: [
template: [type: 'text size: 80x25]
init: [
react/link func [f _] [
[f/data f/offset f/size] ;) define reactive sources (3 sources = 3 reactions)
f/text: "text"
] [face face]
]
]
]
view/no-wait [p: panel []]
count: 100
recycle/off
print "=== BASELINE (VIEW ONLY) ==="
print ""
print ["CREATING" count "FACES x5"]
loop 5 [clock [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]]
print ["SHOWING" count "FACES"]
print ["p/pane:" length? p/pane "faces"]
clock [show p]
clear p/pane
clock [recycle]
print ""
print "=== WITH REACTIVITY ==="
print ""
print ["CREATING" count "FACES & x3 REACTIONS x5 (A TOTAL OF" count * 15 "REACTIONS)"]
loop 5 [clock [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]]
print ["SHOWING" count "FACES & DESTROYING" count * 12 "REACTIONS"]
print ["p/pane:" length? p/pane "faces"]
print ["relations count:" (length? system/reactivity/relations) / 4]
clock [show p]
print ["relations count:" (length? system/reactivity/relations) / 4]
clear p/pane
clock [recycle]
=== BASELINE (VIEW ONLY) ===
CREATING 100 FACES x5
10.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
11.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
10.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
8.99 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
8.99 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
SHOWING 100 FACES
p/pane: 100 faces
337 ms [show p]
4.00 ms [recycle]
=== WITH REACTIVITY ===
CREATING 100 FACES & x3 REACTIONS x5 (A TOTAL OF 1500 REACTIONS)
15.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
20.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
24.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
29.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
32.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
SHOWING 100 FACES & DESTROYING 1200 REACTIONS
p/pane: 100 faces
relations count: 1500
612 ms [show p]
relations count: 300
4.00 ms [recycle]
=== BASELINE (VIEW ONLY) ===
CREATING 250 FACES x5
26.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
22.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
23.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
23.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
24.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
SHOWING 250 FACES
p/pane: 250 faces
831 ms [show p]
16.0 ms [recycle]
=== WITH REACTIVITY ===
CREATING 250 FACES & x3 REACTIONS x5 (A TOTAL OF 3750 REACTIONS)
47.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
76.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
99.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
128 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
153 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
SHOWING 250 FACES & DESTROYING 3000 REACTIONS
p/pane: 250 faces
relations count: 3750
2352 ms [show p]
relations count: 750
17.9 ms [recycle]
=== BASELINE (VIEW ONLY) ===
CREATING 500 FACES x5
46.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
46.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
47.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
47.0 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
45.9 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text1]]]
SHOWING 500 FACES
p/pane: 500 faces
1797 ms [show p]
69.0 ms [recycle]
=== WITH REACTIVITY ===
CREATING 500 FACES & x3 REACTIONS x5 (A TOTAL OF 7500 REACTIONS)
122 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
225 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
332 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
431 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
531 ms [do-unseen [clear p/pane loop count [append p/pane make-face 'text2]]]
SHOWING 500 FACES & DESTROYING 6000 REACTIONS
p/pane: 500 faces
relations count: 7500
7871 ms [show p]
relations count: 1500
77.0 ms [recycle]
With relations: make hash! 1000
and queue: make hash! 100
and fix red/red@5aa78a6:
=== BASELINE (VIEW ONLY) ===
CREATING 1000 FACES x5
232 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
230 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
230 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
228 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
230 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text1]]]
SHOWING 1000 FACES
p/pane: 1000 faces
2403 ms [show p]
497 ms [recycle]
=== WITH REACTIVITY ===
CREATING 1000 FACES & 3000 REACTIONS x5 (A TOTAL OF 15000 REACTIONS)
529 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
809 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
1264 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
1219 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
2841 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]]
SHOWING 1000 FACES & DESTROYING 12000 REACTIONS
p/pane: 1000 faces
relations count: 15000
41076 ms [show p]
relations count: 3000
562 ms [recycle]
I added pure reactivity test to the tail of script, without involving View (per @dockimbel's advice).
Now I'm getting with blocks:
=== ONLY REACTIVITY (NO VIEW) ===
CREATING 1000 REACTORS x5
44.0 ms [clear pick b 1 loop 1000 [append pick b 1 reactor [x: 10 y: 2 t: 0 re
46.0 ms [clear pick b 2 loop 1000 [append pick b 2 reactor [x: 10 y: 2 t: 0 re
45.0 ms [clear pick b 3 loop 1000 [append pick b 3 reactor [x: 10 y: 2 t: 0 re
43.0 ms [clear pick b 4 loop 1000 [append pick b 4 reactor [x: 10 y: 2 t: 0 re
46.0 ms [clear pick b 5 loop 1000 [append pick b 5 reactor [x: 10 y: 2 t: 0 re
CREATING 15000 REACTIONS
229 ms [foreach r pick b 1 [react/later r/re]]
586 ms [foreach r pick b 2 [react/later r/re]]
930 ms [foreach r pick b 3 [react/later r/re]]
1282 ms [foreach r pick b 4 [react/later r/re]]
1616 ms [foreach r pick b 5 [react/later r/re]]
relations count: 15000
b/1/1/t: 0
b/2/2/t: 0
FIRING 15000 REACTIONS
1834 ms [s/s: 2]
b/1/1/t: 22
b/2/2/t: 22
DESTROYING 15000 REACTIONS
2246 ms [foreach r pick b 1 [react/unlink r/re 'all]]
1741 ms [foreach r pick b 2 [react/unlink r/re 'all]]
1246 ms [foreach r pick b 3 [react/unlink r/re 'all]]
750 ms [foreach r pick b 4 [react/unlink r/re 'all]]
252 ms [foreach r pick b 5 [react/unlink r/re 'all]]
relations count: 0
34.0 ms [recycle]
And with hashes (with #4466 fixed):
=== ONLY REACTIVITY (NO VIEW) ===
CREATING 1000 REACTORS x5
45.0 ms [clear pick b 1 loop 1000 [append pick b 1 reactor [x: 10 y: 2 t: 0 re
43.0 ms [clear pick b 2 loop 1000 [append pick b 2 reactor [x: 10 y: 2 t: 0 re
44.0 ms [clear pick b 3 loop 1000 [append pick b 3 reactor [x: 10 y: 2 t: 0 re
45.0 ms [clear pick b 4 loop 1000 [append pick b 4 reactor [x: 10 y: 2 t: 0 re
52.0 ms [clear pick b 5 loop 1000 [append pick b 5 reactor [x: 10 y: 2 t: 0 re
CREATING 15000 REACTIONS
500 ms [foreach r pick b 1 [react/later r/re]]
1464 ms [foreach r pick b 2 [react/later r/re]]
3099 ms [foreach r pick b 3 [react/later r/re]]
3060 ms [foreach r pick b 4 [react/later r/re]]
8417 ms [foreach r pick b 5 [react/later r/re]]
relations count: 15000
b/1/1/t: 0
b/2/2/t: 0
FIRING 15000 REACTIONS
1567 ms [s/s: 2]
b/1/1/t: 22
b/2/2/t: 22
DESTROYING 15000 REACTIONS
3044 ms [foreach r pick b 1 [react/unlink r/re 'all]]
2379 ms [foreach r pick b 2 [react/unlink r/re 'all]]
1702 ms [foreach r pick b 3 [react/unlink r/re 'all]]
1014 ms [foreach r pick b 4 [react/unlink r/re 'all]]
341 ms [foreach r pick b 5 [react/unlink r/re 'all]]
relations count: 0
34.0 ms [recycle]
Looks like hash is up to 5 times slower ;) And also non-linear in it's complexity growth (depends on the bucket size??).
stop-reactor
is linear though (used by View only), needs a fix. But other linear or worse timings are curious, not obvious right away. red/red#3536 ?
I'm getting better timings when all objects are mostly unique in relations
(added test 4 to the script):
=== ONLY REACTIVITY AND OBJECTS MAINLY UNIQUE ===
CREATING 1000 REACTORS x5
35.0 ms [clear pick b 1 loop 1000 [append pick b 1 make s [re: copy/deep re]]]
33.0 ms [clear pick b 2 loop 1000 [append pick b 2 make s [re: copy/deep re]]]
33.0 ms [clear pick b 3 loop 1000 [append pick b 3 make s [re: copy/deep re]]]
32.0 ms [clear pick b 4 loop 1000 [append pick b 4 make s [re: copy/deep re]]]
38.0 ms [clear pick b 5 loop 1000 [append pick b 5 make s [re: copy/deep re]]]
CREATING 15000 REACTIONS
184 ms [foreach r pick b 1 [react/link/later r/re: func [this that] r/re [r p
452 ms [foreach r pick b 2 [react/link/later r/re: func [this that] r/re [r p
912 ms [foreach r pick b 3 [react/link/later r/re: func [this that] r/re [r p
852 ms [foreach r pick b 4 [react/link/later r/re: func [this that] r/re [r p
2446 ms [foreach r pick b 5 [react/link/later r/re: func [this that] r/re [r p
relations count: 15000
b/1/1/t: 0
b/2/2/t: 0
FIRING 15000 REACTIONS
552 ms [s/t: 1]
b/1/1/t: 1
b/2/2/t: 1
DESTROYING 15000 REACTIONS
922 ms [foreach r pick b 1 [react/unlink :r/re 'all]]
719 ms [foreach r pick b 2 [react/unlink :r/re 'all]]
515 ms [foreach r pick b 3 [react/unlink :r/re 'all]]
313 ms [foreach r pick b 4 [react/unlink :r/re 'all]]
112 ms [foreach r pick b 5 [react/unlink :r/re 'all]]
root: 4720/6799, runs: 0, mem: 49425200
(nevermind the GC caused crash)