@@ -20,12 +20,14 @@ const enum AbsentReason {
2020 Sentinel = "Sentinel" ,
2121}
2222
23- interface OptionalValue {
24- absentReason : AbsentReason | undefined ;
25- tuples : number ;
23+ type Optional < T > = AbsentReason | T ;
24+
25+ function isPresent < T > ( x : Optional < T > ) : x is T {
26+ return typeof x !== "string" ;
2627}
2728
28- interface PredicateInfo extends OptionalValue {
29+ interface PredicateInfo {
30+ tuples : number ;
2931 evaluationCount : number ;
3032 iterationCount : number ;
3133 timeCost : number ;
@@ -47,41 +49,32 @@ class ComparisonDataset {
4749 this . sentinelEmptyIndices = new Set ( data . sentinelEmptyIndices ) ;
4850 }
4951
50- getTupleCountInfo ( name : string ) : PredicateInfo {
52+ getTupleCountInfo ( name : string ) : Optional < PredicateInfo > {
5153 const { data, nameToIndex, cacheHitIndices, sentinelEmptyIndices } = this ;
5254 const index = nameToIndex . get ( name ) ;
5355 if ( index == null ) {
54- return {
55- evaluationCount : 0 ,
56- iterationCount : 0 ,
57- tuples : 0 ,
58- timeCost : 0 ,
59- absentReason : AbsentReason . NotSeen ,
60- pipelines : { } ,
61- } ;
56+ return AbsentReason . NotSeen ;
6257 }
6358 const tupleCost = data . tupleCosts [ index ] ;
64- let absentReason : AbsentReason | undefined ;
6559 if ( tupleCost === 0 ) {
6660 if ( sentinelEmptyIndices . has ( index ) ) {
67- absentReason = AbsentReason . Sentinel ;
61+ return AbsentReason . Sentinel ;
6862 } else if ( cacheHitIndices . has ( index ) ) {
69- absentReason = AbsentReason . CacheHit ;
63+ return AbsentReason . CacheHit ;
7064 }
7165 }
7266 return {
7367 evaluationCount : data . evaluationCounts [ index ] ,
7468 iterationCount : data . iterationCounts [ index ] ,
7569 timeCost : data . timeCosts [ index ] ,
7670 tuples : tupleCost ,
77- absentReason,
7871 pipelines : data . pipelineSummaryList [ index ] ,
7972 } ;
8073 }
8174}
8275
83- function renderAbsoluteValue ( x : PredicateInfo , metric : Metric ) {
84- switch ( x . absentReason ) {
76+ function renderAbsoluteValue ( x : Optional < PredicateInfo > , metric : Metric ) {
77+ switch ( x ) {
8578 case AbsentReason . NotSeen :
8679 return < AbsentNumberCell > n/a</ AbsentNumberCell > ;
8780 case AbsentReason . CacheHit :
@@ -251,17 +244,18 @@ const HeaderTR = styled.tr`
251244` ;
252245
253246interface HighLevelStatsProps {
254- before : PredicateInfo ;
255- after : PredicateInfo ;
247+ before : Optional < PredicateInfo > ;
248+ after : Optional < PredicateInfo > ;
256249 comparison : boolean ;
257250}
258251
259252function HighLevelStats ( props : HighLevelStatsProps ) {
260253 const { before, after, comparison } = props ;
261- const hasBefore = before . absentReason !== AbsentReason . NotSeen ;
262- const hasAfter = after . absentReason !== AbsentReason . NotSeen ;
254+ const hasBefore = isPresent ( before ) ;
255+ const hasAfter = isPresent ( after ) ;
263256 const showEvaluationCount =
264- before . evaluationCount > 1 || after . evaluationCount > 1 ;
257+ ( hasBefore && before . evaluationCount > 1 ) ||
258+ ( hasAfter && after . evaluationCount > 1 ) ;
265259 return (
266260 < >
267261 < HeaderTR >
@@ -275,15 +269,19 @@ function HighLevelStats(props: HighLevelStatsProps) {
275269 </ HeaderTR >
276270 { showEvaluationCount && (
277271 < PipelineStep
278- before = { before . evaluationCount || undefined }
279- after = { after . evaluationCount || undefined }
272+ before = { hasBefore ? before . evaluationCount : undefined }
273+ after = { hasAfter ? after . evaluationCount : undefined }
280274 comparison = { comparison }
281275 step = "Number of evaluations"
282276 />
283277 ) }
284278 < PipelineStep
285- before = { before . iterationCount / before . evaluationCount || undefined }
286- after = { after . iterationCount / after . evaluationCount || undefined }
279+ before = {
280+ hasBefore ? before . iterationCount / before . evaluationCount : undefined
281+ }
282+ after = {
283+ hasAfter ? after . iterationCount / after . evaluationCount : undefined
284+ }
287285 comparison = { comparison }
288286 step = {
289287 showEvaluationCount
@@ -297,8 +295,8 @@ function HighLevelStats(props: HighLevelStatsProps) {
297295
298296interface TRow {
299297 name : string ;
300- before : PredicateInfo ;
301- after : PredicateInfo ;
298+ before : Optional < PredicateInfo > ;
299+ after : Optional < PredicateInfo > ;
302300 diff : number ;
303301}
304302
@@ -332,14 +330,23 @@ const metrics: Record<string, Metric> = {
332330 iterations : {
333331 title : "Iterations (per evaluation)" ,
334332 get : ( info ) =>
335- info . absentReason ? 0 : info . iterationCount / info . evaluationCount ,
333+ info . evaluationCount === 0
334+ ? 0
335+ : info . iterationCount / info . evaluationCount ,
336336 } ,
337337 iterationsTotal : {
338338 title : "Iterations (total)" ,
339339 get : ( info ) => info . iterationCount ,
340340 } ,
341341} ;
342342
343+ function metricGetOptional (
344+ metric : Metric ,
345+ value : Optional < PredicateInfo > ,
346+ ) : Optional < number > {
347+ return isPresent ( value ) ? metric . get ( value ) : value ;
348+ }
349+
343350function Chevron ( { expanded } : { expanded : boolean } ) {
344351 return < Codicon name = { expanded ? "chevron-down" : "chevron-right" } /> ;
345352}
@@ -419,21 +426,23 @@ function ComparePerformanceWithData(props: {
419426 . map ( ( name ) => {
420427 const before = from . getTupleCountInfo ( name ) ;
421428 const after = to . getTupleCountInfo ( name ) ;
422- const beforeValue = metric . get ( before ) ;
423- const afterValue = metric . get ( after ) ;
429+ const beforeValue = metricGetOptional ( metric , before ) ;
430+ const afterValue = metricGetOptional ( metric , after ) ;
424431 if ( beforeValue === afterValue ) {
425432 return undefined ! ;
426433 }
427434 if (
428- before . absentReason === AbsentReason . CacheHit ||
429- after . absentReason === AbsentReason . CacheHit
435+ before === AbsentReason . CacheHit ||
436+ after === AbsentReason . CacheHit
430437 ) {
431438 hasCacheHitMismatch . current = true ;
432439 if ( hideCacheHits ) {
433440 return undefined ! ;
434441 }
435442 }
436- const diff = afterValue - beforeValue ;
443+ const diff =
444+ ( isPresent ( afterValue ) ? afterValue : 0 ) -
445+ ( isPresent ( beforeValue ) ? beforeValue : 0 ) ;
437446 return { name, before, after, diff } satisfies TRow ;
438447 } )
439448 . filter ( ( x ) => ! ! x )
@@ -445,8 +454,8 @@ function ComparePerformanceWithData(props: {
445454 let totalAfter = 0 ;
446455 let totalDiff = 0 ;
447456 for ( const row of rows ) {
448- totalBefore += metric . get ( row . before ) ;
449- totalAfter += metric . get ( row . after ) ;
457+ totalBefore += isPresent ( row . before ) ? metric . get ( row . before ) : 0 ;
458+ totalAfter += isPresent ( row . after ) ? metric . get ( row . after ) : 0 ;
450459 totalDiff += row . diff ;
451460 }
452461 return { totalBefore, totalAfter, totalDiff } ;
@@ -543,8 +552,8 @@ function ComparePerformanceWithData(props: {
543552 comparison = { comparison }
544553 />
545554 { collatePipelines (
546- row . before . pipelines ,
547- row . after . pipelines ,
555+ isPresent ( row . before ) ? row . before . pipelines : { } ,
556+ isPresent ( row . after ) ? row . after . pipelines : { } ,
548557 ) . map ( ( { name, first, second } , pipelineIndex ) => (
549558 < Fragment key = { pipelineIndex } >
550559 < HeaderTR >
0 commit comments