@@ -97,6 +97,75 @@ class ComparisonDataset {
97
97
pipelines : data . pipelineSummaryList [ index ] ,
98
98
} ;
99
99
}
100
+
101
+ /**
102
+ * Returns the RA hashes of all predicates that were evaluated in this data set, but not seen in `other`,
103
+ * because in `other` the dependency upon these predicates was cut off by a cache hit.
104
+ *
105
+ * For example, suppose predicate `A` depends on `B`, which depends on `C`, and the
106
+ * predicates were evaluated in the first log but not the second:
107
+ * ```
108
+ * first eval. log second eval. log
109
+ * predicate A seen evaluation seen cache hit
110
+ * |
111
+ * V
112
+ * predicate B seen evaluation not seen
113
+ * |
114
+ * V
115
+ * predicate C seen evaluation not seen
116
+ * ```
117
+ *
118
+ * To ensure a meaningful comparison, we want to omit `predicate A` from the comparison view because of the cache hit.
119
+ *
120
+ * But predicates B and C did not have a recorded cache hit in the second log, because they were never scheduled for evaluation.
121
+ * Given the dependency graph, the most likely explanation is that they would have been evaluated if `A` had not been a cache hit.
122
+ * We therefore say that B and C are "shadowed" by the cache hit on A.
123
+ *
124
+ * The dependency graph is only visible in the first evaluation log, because `B` and `C` do not exist in the second log.
125
+ * So to compute this, we use the dependency graph from one log together with the set of cache hits in the other log.
126
+ */
127
+ getPredicatesShadowedByCacheHit ( other : ComparisonDataset ) {
128
+ const {
129
+ data : { dependencyLists, raHashes, names } ,
130
+ raToIndex,
131
+ } = this ;
132
+ const cacheHits = new Set < string > ( ) ;
133
+
134
+ function visit ( index : number , raHash : string ) {
135
+ if ( cacheHits . has ( raHash ) ) {
136
+ return ;
137
+ }
138
+ cacheHits . add ( raHash ) ;
139
+ const dependencies = dependencyLists [ index ] ;
140
+ for ( const dep of dependencies ) {
141
+ const name = names [ dep ] ;
142
+ if ( ! other . nameToIndex . has ( name ) ) {
143
+ visit ( dep , raHashes [ dep ] ) ;
144
+ }
145
+ }
146
+ }
147
+
148
+ for ( const otherCacheHit of other . cacheHitIndices ) {
149
+ {
150
+ // Look up by RA hash
151
+ const raHash = other . data . raHashes [ otherCacheHit ] ;
152
+ const ownIndex = raToIndex . get ( raHash ) ;
153
+ if ( ownIndex != null ) {
154
+ visit ( ownIndex , raHash ) ;
155
+ }
156
+ }
157
+ {
158
+ // Look up by name
159
+ const name = other . data . names [ otherCacheHit ] ;
160
+ const ownIndex = this . nameToIndex . get ( name ) ;
161
+ if ( ownIndex != null ) {
162
+ visit ( ownIndex , this . data . raHashes [ ownIndex ] ) ;
163
+ }
164
+ }
165
+ }
166
+
167
+ return cacheHits ;
168
+ }
100
169
}
101
170
102
171
function renderOptionalValue ( x : Optional < number > , unit : string | undefined ) {
@@ -503,6 +572,17 @@ function ComparePerformanceWithData(props: {
503
572
504
573
const hasCacheHitMismatch = useRef ( false ) ;
505
574
575
+ const shadowedCacheHitsFrom = useMemo (
576
+ ( ) =>
577
+ hideCacheHits ? from . getPredicatesShadowedByCacheHit ( to ) : new Set ( ) ,
578
+ [ from , to , hideCacheHits ] ,
579
+ ) ;
580
+ const shadowedCacheHitsTo = useMemo (
581
+ ( ) =>
582
+ hideCacheHits ? to . getPredicatesShadowedByCacheHit ( from ) : new Set ( ) ,
583
+ [ from , to , hideCacheHits ] ,
584
+ ) ;
585
+
506
586
const rows : Row [ ] = useMemo ( ( ) => {
507
587
hasCacheHitMismatch . current = false ;
508
588
return Array . from ( keySet )
@@ -523,6 +603,16 @@ function ComparePerformanceWithData(props: {
523
603
return undefined ! ;
524
604
}
525
605
}
606
+ if (
607
+ ( isPresent ( before ) &&
608
+ ! isPresent ( after ) &&
609
+ shadowedCacheHitsFrom . has ( before . raHash ) ) ||
610
+ ( isPresent ( after ) &&
611
+ ! isPresent ( before ) &&
612
+ shadowedCacheHitsTo . has ( after . raHash ) )
613
+ ) {
614
+ return undefined ! ;
615
+ }
526
616
const diff =
527
617
( isPresent ( afterValue ) ? afterValue : 0 ) -
528
618
( isPresent ( beforeValue ) ? beforeValue : 0 ) ;
0 commit comments