@@ -66,6 +66,12 @@ public let benchmarks = [
6666 tags: [ . validation, . api] ,
6767 setUpFunction: setupKeyPathNestedStructs
6868 ) ,
69+ BenchmarkInfo (
70+ name: " KeyPathClassStructs " ,
71+ runFunction: run_KeyPathClassStructs,
72+ tags: [ . validation, . api] ,
73+ setUpFunction: setupKeyPathNestedStructs
74+ ) ,
6975]
7076
7177/**
@@ -97,6 +103,7 @@ class FixedSizeArrayHolder {
97103 var fixedSizeArray100 : FixedSizeArray100 < ElementType >
98104 var fixedSizeArray10 : FixedSizeArray10 < ElementType >
99105 var mainArrayForNestedStructs : [ A ]
106+ var mainArrayForClassStructs : [ D1 ]
100107 var arrayForMutatingGetset : [ MutatingGetsetNested1 ]
101108 var arrayForGet : [ GetNested1 ]
102109 var arrayForOptionals : [ Optional1 ]
@@ -107,6 +114,7 @@ class FixedSizeArrayHolder {
107114 var keypathForOptional : KeyPath < Optional1 , Int ? >
108115 var keypathForNestedClasses : KeyPath < C1 , Int >
109116 var keypathForNonMutatingGetset : WritableKeyPath < M , Int >
117+ var keypathForClassStructs : WritableKeyPath < D1 , Int >
110118
111119 // Same order as in KeyPathWritePerformance
112120 var kp46 : WritableKeyPath < FixedSizeArray100 < ElementType > , ElementType >
@@ -176,6 +184,7 @@ class FixedSizeArrayHolder {
176184 fixedSizeArray100 = initializeFixedSizeArray100 ( )
177185 fixedSizeArray10 = initializeFixedSizeArray10 ( )
178186 mainArrayForNestedStructs = [ A] ( )
187+ mainArrayForClassStructs = [ D1] ( )
179188 arrayForMutatingGetset = [ MutatingGetsetNested1] ( )
180189 arrayForGet = [ GetNested1] ( )
181190 arrayForOptionals = [ Optional1] ( )
@@ -252,6 +261,7 @@ class FixedSizeArrayHolder {
252261 . _nestedItemStorage?! . _nestedItemStorage?! . _storage)
253262 keypathForNestedClasses = identity ( \C1 . r. r. r. r. a)
254263 keypathForNonMutatingGetset = identity ( \M . n. o. p. q. q)
264+ keypathForClassStructs = identity ( \D1 . b. c. d. e. e)
255265 }
256266}
257267
@@ -262,6 +272,10 @@ public func setupKeyPathNestedStructs() {
262272 let instance = A ( a: 0 , b: B ( b: 0 , c: C ( c: 0 , d: D ( d: 0 , e: E ( e: expectedIntForNestedItems) ) ) ) )
263273 holder. mainArrayForNestedStructs. append ( instance)
264274
275+ let classStructInstance = D1 ( b: D2 ( b: 0 , c: D3 ( c: 0 , d: D4 ( d: 0 ,
276+ e: D5 ( e: expectedIntForNestedItems) ) ) ) )
277+ holder. mainArrayForClassStructs. append ( classStructInstance)
278+
265279 var mutatingGetsetInstance = MutatingGetsetNested1 ( )
266280 mutatingGetsetInstance. nestedItem. nestedItem. nestedItem. nestedItem
267281 . storage = expectedIntForNestedItems
@@ -333,6 +347,36 @@ struct E {
333347 var e : Int
334348}
335349
350+ // Used for run_KeyPathClassStruct().
351+ class D1 {
352+ var a : Int
353+ var b : D2
354+ init ( b: D2 )
355+ {
356+ a = 0
357+ self . b = b
358+ }
359+ }
360+
361+ struct D2 {
362+ var b : Int
363+ var c : D3
364+ }
365+
366+ struct D3 {
367+ var c : Int
368+ var d : D4
369+ }
370+
371+ struct D4 {
372+ var d : Int
373+ var e : D5
374+ }
375+
376+ struct D5 {
377+ var e : Int
378+ }
379+
336380// Used for run_KeyPathNestedClasses()
337381class C1 {
338382 let a : Int = 0
@@ -1326,6 +1370,36 @@ public func run_KeyPathNestedStructs(n: Int) {
13261370 check ( sum == iterationMultipier * n * expectedIntForNestedItems)
13271371}
13281372
1373+ // This measures the performance of keypath reads where a block of
1374+ // trivially-typed memory is preceded by something else (optionals, reference
1375+ // types, etc.)
1376+ @inline ( never)
1377+ public func run_KeyPathClassStructs( n: Int ) {
1378+ var sum = 0
1379+ var index = 0
1380+ let iterationMultipier = 500
1381+
1382+ let singleHopKeyPath0 : WritableKeyPath < D1 , D2 > = \D1 . b
1383+ let singleHopKeyPath1 : WritableKeyPath < D2 , D3 > = \D2 . c
1384+ let singleHopKeyPath2 : WritableKeyPath < D3 , D4 > = \D3 . d
1385+ let singleHopKeyPath3 : WritableKeyPath < D4 , D5 > = \D4 . e
1386+ let singleHopKeyPath4 : WritableKeyPath < D5 , Int > = \D5 . e
1387+
1388+ let appendedKeyPath = identity ( singleHopKeyPath0. appending ( path: singleHopKeyPath1)
1389+ . appending ( path: singleHopKeyPath2) . appending ( path: singleHopKeyPath3)
1390+ . appending ( path: singleHopKeyPath4) )
1391+
1392+ let elementCount = FixedSizeArrayHolder . shared. mainArrayForClassStructs. count
1393+ for _ in 1 ... iterationMultipier * n {
1394+ let element = FixedSizeArrayHolder . shared. mainArrayForClassStructs [ index]
1395+ sum += element [ keyPath: appendedKeyPath]
1396+ index = ( index + 1 ) % elementCount
1397+ }
1398+ check ( sum == iterationMultipier * n * expectedIntForNestedItems)
1399+ }
1400+
1401+
1402+
13291403// This is meant as a baseline, from a timing perspective,
13301404// for run_testKeyPathReadPerformance() and run_testKeyPathWritePerformance().
13311405// It's currently set to ".skip", but is useful for comparing the performance between keypath operations and direct dot-notation.
0 commit comments