Skip to content

Instantly share code, notes, and snippets.

@hiiamboris
Last active May 25, 2020 15:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hiiamboris/4da1bccf63f4506b412977c1673c723c to your computer and use it in GitHub Desktop.
Save hiiamboris/4da1bccf63f4506b412977c1673c723c to your computer and use it in GitHub Desktop.
Reactivity benchmark
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
Copy link
Author

=== 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]]] 
229 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                                                            
2217 ms [show p]                                                              
475 ms  [recycle]                                                             
                                                                              
=== WITH REACTIVITY ===                                                       
                                                                              
CREATING 1000 FACES & 3000 REACTIONS x5 (A TOTAL OF 15000 REACTIONS)          
739 ms  [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]] 
1440 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]] 
2123 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]] 
2766 ms [do-unseen [clear p/pane loop 1000 [append p/pane make-face 'text2]]] 
3401 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                                                        
38956 ms        [show p]                                                      
relations count: 3000                                                         
547 ms  [recycle]                                                             

@hiiamboris
Copy link
Author

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]                                                              

@greggirwin
Copy link

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]

@greggirwin
Copy link

=== 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]

@greggirwin
Copy link

=== 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]

@greggirwin
Copy link

=== 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]

@hiiamboris
Copy link
Author

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]                                                            

@hiiamboris
Copy link
Author

hiiamboris commented May 25, 2020

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??).

@hiiamboris
Copy link
Author

hiiamboris commented May 25, 2020

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 ?

@hiiamboris
Copy link
Author

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment