1- import * as I from "immutable" ;
21import {
32 EvaluationLogProblemReporter ,
43 EvaluationLogScanner ,
@@ -37,7 +36,7 @@ function makeKey(
3736 return `${ queryCausingWork } :${ predicate } ${ suffix ? ` ${ suffix } ` : "" } ` ;
3837}
3938
40- function getDependentPredicates ( operations : string [ ] ) : I . List < string > {
39+ function getDependentPredicates ( operations : string [ ] ) : string [ ] {
4140 const id = String . raw `[0-9a-zA-Z:#_\./]+` ;
4241 const idWithAngleBrackets = String . raw `[0-9a-zA-Z:#_<>\./]+` ;
4342 const quotedId = String . raw `\`[^\`\r\n]*\`` ;
@@ -68,10 +67,10 @@ function getDependentPredicates(operations: string[]): I.List<string> {
6867 String . raw `\{[0-9]+\}\s+(?:[0-9a-zA-Z]+\s=|\|)\s(?:` + regexps . join ( "|" )
6968 } )`,
7069 ) ;
71- return I . List ( operations ) . flatMap ( ( operation ) => {
70+ return operations . flatMap ( ( operation ) => {
7271 const matches = r . exec ( operation . trim ( ) ) || [ ] ;
73- return I . List ( matches )
74- . rest ( ) // Skip the first group as it's just the entire string
72+ return matches
73+ . slice ( 1 ) // Skip the first group as it's just the entire string
7574 . filter ( ( x ) => ! ! x )
7675 . flatMap ( ( x ) => x . split ( "," ) ) // Group 2 in the INVOKE HIGHER_ORDER RELATION case is a comma-separated list of identifiers.
7776 . flatMap ( ( x ) => x . split ( " UNION " ) ) // Split n-ary unions into individual arguments.
@@ -152,7 +151,7 @@ function computeJoinOrderBadness(
152151interface Bucket {
153152 tupleCounts : Int32Array ;
154153 resultSize : number ;
155- dependentPredicateSizes : I . Map < string , number > ;
154+ dependentPredicateSizes : Map < string , number > ;
156155}
157156
158157class JoinOrderScanner implements EvaluationLogScanner {
@@ -407,12 +406,12 @@ class JoinOrderScanner implements EvaluationLogScanner {
407406 const dependentPredicates = getDependentPredicates (
408407 inLayerEvent . ra [ raReference ] ,
409408 ) ;
410- let dependentPredicateSizes : I . Map < string , number > ;
409+ let dependentPredicateSizes : Map < string , number > ;
411410 // We treat the base case as a non-recursive pipeline. In that case, the dependent predicates are
412411 // the dependencies of the base case and the cur_deltas.
413412 if ( raReference === "base" ) {
414- dependentPredicateSizes = I . Map (
415- dependentPredicates . map ( ( pred ) : [ string , number ] => {
413+ dependentPredicateSizes = dependentPredicates
414+ . map ( ( pred ) : [ string , number ] => {
416415 // A base case cannot contain a `prev_delta`, but it can contain a `cur_delta`.
417416 let size = 0 ;
418417 if ( pred . endsWith ( "#cur_delta" ) ) {
@@ -426,28 +425,27 @@ class JoinOrderScanner implements EvaluationLogScanner {
426425 size = this . predicateSizes . get ( hash ) ! ;
427426 }
428427 return [ pred , size ] ;
429- } ) ,
430- ) ;
428+ } )
429+ . reduce ( ( acc , [ pred , size ] ) => acc . set ( pred , size ) , new Map ( ) ) ;
431430 } else {
432431 // It's a non-base case in a recursive pipeline. In that case, the dependent predicates are
433432 // only the prev_deltas.
434- dependentPredicateSizes = I . Map (
435- dependentPredicates
436- . flatMap ( ( pred ) => {
437- // If it's actually a prev_delta
438- if ( pred . endsWith ( "#prev_delta" ) ) {
439- // Return the predicate without the #prev_delta suffix.
440- return [ pred . slice ( 0 , - "#prev_delta" . length ) ] ;
441- } else {
442- // Not a recursive delta. Skip it.
443- return [ ] ;
444- }
445- } )
446- . map ( ( prev ) : [ string , number ] => {
447- const size = this . prevDeltaSizes ( event , prev , iteration ) ;
448- return [ prev , size ] ;
449- } ) ,
450- ) ;
433+ dependentPredicateSizes = dependentPredicates
434+ . flatMap ( ( pred ) => {
435+ // If it's actually a prev_delta
436+ if ( pred . endsWith ( "#prev_delta" ) ) {
437+ // Return the predicate without the #prev_delta suffix.
438+ return [ pred . slice ( 0 , - "#prev_delta" . length ) ] ;
439+ } else {
440+ // Not a recursive delta. Skip it.
441+ return [ ] ;
442+ }
443+ } )
444+ . map ( ( prev ) : [ string , number ] => {
445+ const size = this . prevDeltaSizes ( event , prev , iteration ) ;
446+ return [ prev , size ] ;
447+ } )
448+ . reduce ( ( acc , [ pred , size ] ) => acc . set ( pred , size ) , new Map ( ) ) ;
451449 }
452450
453451 const deltaSize = inLayerEvent . deltaSizes [ iteration ] ;
@@ -475,7 +473,7 @@ class JoinOrderScanner implements EvaluationLogScanner {
475473 orderTobucket . set ( raReference , {
476474 tupleCounts : new Int32Array ( 0 ) ,
477475 resultSize : 0 ,
478- dependentPredicateSizes : I . Map ( ) ,
476+ dependentPredicateSizes : new Map ( ) ,
479477 } ) ;
480478 }
481479
@@ -494,12 +492,18 @@ class JoinOrderScanner implements EvaluationLogScanner {
494492 this . problemReporter ,
495493 ) ;
496494 const resultSize = bucket . resultSize + deltaSize ;
495+
497496 // Pointwise sum the deltas.
498- const newDependentPredicateSizes =
499- bucket . dependentPredicateSizes . mergeWith (
500- ( oldSize , newSize ) => oldSize + newSize ,
501- dependentPredicateSizes ,
497+ const newDependentPredicateSizes = new Map < string , number > (
498+ bucket . dependentPredicateSizes ,
499+ ) ;
500+ for ( const [ pred , size ] of dependentPredicateSizes ) {
501+ newDependentPredicateSizes . set (
502+ pred ,
503+ ( newDependentPredicateSizes . get ( pred ) ?? 0 ) + size ,
502504 ) ;
505+ }
506+
503507 orderTobucket . set ( raReference , {
504508 tupleCounts : newTupleCounts ,
505509 resultSize,
0 commit comments