1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using System . Collections . Immutable ;
4
+ using System . Linq ;
5
+ using System . Text ;
6
+ using Akka . Benchmarks . Configurations ;
7
+ using Akka . Cluster ;
8
+ using Akka . DistributedData ;
9
+ using BenchmarkDotNet . Attributes ;
10
+ using FluentAssertions ;
11
+ using static Akka . DistributedData . VersionVector ;
12
+
13
+ namespace Akka . Benchmarks . DData
14
+ {
15
+ [ Config ( typeof ( MicroBenchmarkConfig ) ) ]
16
+ public class VersionVectorBenchmarks
17
+ {
18
+ [ Params ( 100 ) ]
19
+ public int ClockSize ;
20
+
21
+ [ Params ( 1000 ) ]
22
+ public int Iterations ;
23
+
24
+ internal ( VersionVector clock , ImmutableSortedSet < UniqueAddress > nodes ) CreateVectorClockOfSize ( int size )
25
+ {
26
+ UniqueAddress GenerateUniqueAddress ( int nodeCount ) {
27
+ return new UniqueAddress ( new Akka . Actor . Address ( "akka.tcp" , "ClusterSys" , "localhost" , nodeCount ) , nodeCount ) ;
28
+ }
29
+
30
+ return Enumerable . Range ( 1 , size )
31
+ . Aggregate ( ( VersionVector . Empty , ImmutableSortedSet < UniqueAddress > . Empty ) ,
32
+ ( tuple , i ) =>
33
+ {
34
+ var ( vc , nodes ) = tuple ;
35
+ var node = GenerateUniqueAddress ( i ) ;
36
+ return ( vc . Increment ( node ) , nodes . Add ( node ) ) ;
37
+ } ) ;
38
+ }
39
+
40
+ internal VersionVector CopyVectorClock ( VersionVector vc )
41
+ {
42
+ var versions = ImmutableDictionary < UniqueAddress , long > . Empty ;
43
+ var enumerator = vc . VersionEnumerator ;
44
+ while ( enumerator . MoveNext ( ) ) {
45
+ var nodePair = enumerator . Current ;
46
+ versions = versions . SetItem ( nodePair . Key , nodePair . Value ) ;
47
+ }
48
+
49
+ return VersionVector . Create ( versions ) ;
50
+ }
51
+
52
+ private UniqueAddress _firstNode ;
53
+ private UniqueAddress _lastNode ;
54
+ private UniqueAddress _middleNode ;
55
+ private ImmutableSortedSet < UniqueAddress > _nodes ;
56
+ private VersionVector _vcBefore ;
57
+ private VersionVector _vcBaseLast ;
58
+ private VersionVector _vcAfterLast ;
59
+ private VersionVector _vcConcurrentLast ;
60
+ private VersionVector _vcBaseMiddle ;
61
+ private VersionVector _vcAfterMiddle ;
62
+ private VersionVector _vcConcurrentMiddle ;
63
+
64
+ [ GlobalSetup ]
65
+ public void Setup ( )
66
+ {
67
+ var ( vcBefore , nodes ) = CreateVectorClockOfSize ( ClockSize ) ;
68
+ _vcBefore = vcBefore ;
69
+ _nodes = nodes ;
70
+
71
+ _firstNode = nodes . First ( ) ;
72
+ _lastNode = nodes . Last ( ) ;
73
+ _middleNode = nodes [ ClockSize / 2 ] ;
74
+
75
+ _vcBaseLast = vcBefore . Increment ( _lastNode ) ;
76
+ _vcAfterLast = _vcBaseLast . Increment ( _firstNode ) ;
77
+ _vcConcurrentLast = _vcBaseLast . Increment ( _lastNode ) ;
78
+ _vcBaseMiddle = _vcBefore . Increment ( _middleNode ) ;
79
+ _vcAfterMiddle = _vcBaseMiddle . Increment ( _firstNode ) ;
80
+ _vcConcurrentMiddle = _vcBaseMiddle . Increment ( _middleNode ) ;
81
+ }
82
+
83
+ private void CheckThunkFor ( VersionVector vc1 , VersionVector vc2 , Action < VersionVector , VersionVector > thunk , int times )
84
+ {
85
+ var vcc1 = CopyVectorClock ( vc1 ) ;
86
+ var vcc2 = CopyVectorClock ( vc2 ) ;
87
+ for ( var i = 0 ; i < times ; i ++ )
88
+ {
89
+ thunk ( vcc1 , vcc2 ) ;
90
+ }
91
+ }
92
+
93
+ private void CompareTo ( VersionVector vc1 , VersionVector vc2 , Ordering ordering )
94
+ {
95
+ vc1 . Compare ( vc2 ) . Should ( ) . Be ( ordering ) ;
96
+ }
97
+
98
+ private void NotEqual ( VersionVector vc1 , VersionVector vc2 )
99
+ {
100
+ ( vc1 == vc2 ) . Should ( ) . BeFalse ( ) ;
101
+ }
102
+
103
+ private void Merge ( VersionVector vc1 , VersionVector vc2 )
104
+ {
105
+ vc1 . Merge ( vc2 ) ;
106
+ }
107
+
108
+ [ Benchmark ]
109
+ public void VectorClock_comparisons_should_compare_same ( )
110
+ {
111
+ CheckThunkFor ( _vcBaseLast , _vcBaseLast , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . Same ) , Iterations ) ;
112
+ }
113
+
114
+ [ Benchmark ]
115
+ public void VectorClock_comparisons_should_compare_Before_last ( )
116
+ {
117
+ CheckThunkFor ( _vcBefore , _vcBaseLast , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . Before ) , Iterations ) ;
118
+ }
119
+
120
+ [ Benchmark ]
121
+ public void VectorClock_comparisons_should_compare_After_last ( )
122
+ {
123
+ CheckThunkFor ( _vcAfterLast , _vcBaseLast , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . After ) , Iterations ) ;
124
+ }
125
+
126
+ [ Benchmark ]
127
+ public void VectorClock_comparisons_should_compare_Concurrent_last ( )
128
+ {
129
+ CheckThunkFor ( _vcAfterLast , _vcConcurrentLast , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . Concurrent ) , Iterations ) ;
130
+ }
131
+
132
+ [ Benchmark ]
133
+ public void VectorClock_comparisons_should_compare_Before_middle ( )
134
+ {
135
+ CheckThunkFor ( _vcBefore , _vcBaseMiddle , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . Before ) , Iterations ) ;
136
+ }
137
+
138
+ [ Benchmark ]
139
+ public void VectorClock_comparisons_should_compare_After_middle ( )
140
+ {
141
+ CheckThunkFor ( _vcAfterMiddle , _vcBaseMiddle , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . After ) , Iterations ) ;
142
+ }
143
+
144
+ [ Benchmark ]
145
+ public void VectorClock_comparisons_should_compare_Concurrent_middle ( )
146
+ {
147
+ CheckThunkFor ( _vcAfterMiddle , _vcConcurrentMiddle , ( clock , vectorClock ) => CompareTo ( clock , vectorClock , Ordering . Concurrent ) , Iterations ) ;
148
+ }
149
+
150
+ [ Benchmark ]
151
+ public void VectorClock_comparisons_should_compare_notEquals_Before_Middle ( )
152
+ {
153
+ CheckThunkFor ( _vcBefore , _vcBaseMiddle , ( clock , vectorClock ) => NotEqual ( clock , vectorClock ) , Iterations ) ;
154
+ }
155
+
156
+ [ Benchmark ]
157
+ public void VectorClock_comparisons_should_compare_notEquals_After_Middle ( )
158
+ {
159
+ CheckThunkFor ( _vcAfterMiddle , _vcBaseMiddle , ( clock , vectorClock ) => NotEqual ( clock , vectorClock ) , Iterations ) ;
160
+ }
161
+
162
+ [ Benchmark ]
163
+ public void VectorClock_comparisons_should_compare_notEquals_Concurrent_Middle ( )
164
+ {
165
+ CheckThunkFor ( _vcAfterMiddle , _vcConcurrentMiddle , ( clock , vectorClock ) => NotEqual ( clock , vectorClock ) , Iterations ) ;
166
+ }
167
+
168
+ [ Benchmark ]
169
+ public void VersionVector_merge_Multi_Multi ( )
170
+ {
171
+ CheckThunkFor ( _vcBefore , _vcAfterLast , ( vector , versionVector ) => Merge ( vector , versionVector ) , Iterations ) ;
172
+ }
173
+ }
174
+ }
0 commit comments