@@ -21,12 +21,15 @@ const IS_CI = (() => {
2121 const cursorAgent = Reflect . get ( env , "CURSOR_AGENT" ) ;
2222 return ( ci === true || ci === "true" || ci === "1" ) && ( cursorAgent !== true && cursorAgent !== 'true' && cursorAgent !== "1" ) ;
2323} ) ( ) ;
24- const DEFAULT_LOAD_ROW_COUNT = IS_CI ? 200_000 : 20_000 ;
24+ const DEFAULT_LOAD_ROW_COUNT = IS_CI ? 200_000 : 20_0000 ;
2525const LOAD_PREFILL_MAX_MS = 30_000 ;
2626const LOAD_COUNT_QUERY_MAX_MS = 5_000 ;
2727const LOAD_POINT_MUTATION_MAX_MS = 400 ;
2828const LOAD_SET_ROW_AVG_ITERATIONS = 10 ;
2929const LOAD_SET_ROW_AVG_MAX_MS = 50 ;
30+ const LOAD_ONLINE_MUTATION_MAX_MS = 50 ;
31+ const LOAD_SUBSET_ITERATION_MAX_MS = 50 ;
32+ const LOAD_SUBSET_ITERATION_ROW_COUNT = 1_000 ;
3033const LOAD_TABLE_DELETE_MAX_MS = 20_000 ;
3134const LOAD_DERIVED_INIT_MAX_MS = 90_000 ;
3235const LOAD_DERIVED_COUNT_QUERY_MAX_MS = 10_000 ;
@@ -121,9 +124,10 @@ describe.sequential("bulldozer db performance (real postgres)", () => {
121124 const dbName = dbUrls . full . replace ( / ^ .* \/ / , "" ) . replace ( / \? .* $ / , "" ) ;
122125 const adminSql = postgres ( dbUrls . base , { onnotice : ( ) => undefined } ) ;
123126 const sql = postgres ( dbUrls . full , { onnotice : ( ) => undefined , max : 1 } ) ;
127+ const PERF_STATEMENT_TIMEOUT = "180s" ;
124128
125129 async function runStatements ( statements : SqlStatement [ ] ) {
126- await sql . unsafe ( toExecutableSqlTransaction ( statements ) ) ;
130+ await sql . unsafe ( toExecutableSqlTransaction ( statements , { statementTimeout : PERF_STATEMENT_TIMEOUT } ) ) ;
127131 }
128132
129133 async function readRows ( query : SqlQuery ) {
@@ -515,6 +519,18 @@ describe.sequential("bulldozer db performance (real postgres)", () => {
515519 const setRowAverageMs = setRowIterationTimes . reduce ( ( acc , value ) => acc + value , 0 ) / setRowIterationTimes . length ;
516520 logLine ( `[bulldozer-perf] load setRow average (${ LOAD_SET_ROW_AVG_ITERATIONS } iterations): ${ setRowAverageMs . toFixed ( 1 ) } ms` ) ;
517521 expect ( setRowAverageMs ) . toBeLessThanOrEqual ( LOAD_SET_ROW_AVG_MAX_MS ) ;
522+ const onlineInsert = await measureMs ( "load online setRow insert (stored table)" , async ( ) => {
523+ await runStatements ( table . setRow ( "perf-online-row" , expr ( jsonbLiteral ( { team : "beta" , value : 111 } ) ) ) ) ;
524+ } ) ;
525+ expect ( onlineInsert . elapsedMs ) . toBeLessThanOrEqual ( LOAD_ONLINE_MUTATION_MAX_MS ) ;
526+ const onlineUpdate = await measureMs ( "load online setRow update (stored table)" , async ( ) => {
527+ await runStatements ( table . setRow ( "perf-online-row" , expr ( jsonbLiteral ( { team : "beta" , value : 222 } ) ) ) ) ;
528+ } ) ;
529+ expect ( onlineUpdate . elapsedMs ) . toBeLessThanOrEqual ( LOAD_ONLINE_MUTATION_MAX_MS ) ;
530+ const onlineDelete = await measureMs ( "load online deleteRow (stored table)" , async ( ) => {
531+ await runStatements ( table . deleteRow ( "perf-online-row" ) ) ;
532+ } ) ;
533+ expect ( onlineDelete . elapsedMs ) . toBeLessThanOrEqual ( LOAD_ONLINE_MUTATION_MAX_MS ) ;
518534
519535 const pointDelete = await measureMs ( "load point delete (deleteRow existing)" , async ( ) => {
520536 await runStatements ( table . deleteRow ( `seed-${ Math . floor ( loadRowCount / 2 ) - 1 } ` ) ) ;
@@ -818,6 +834,21 @@ describe.sequential("bulldozer db performance (real postgres)", () => {
818834 expect ( filteredDeltaRows . map ( ( row ) => ( { rowIdentifier : row . rowidentifier , rowData : row . rowdata } ) ) ) . toEqual ( [
819835 { rowIdentifier : "seed-100000:1" , rowData : { team : "delta" , value : 999 } } ,
820836 ] ) ;
837+ const groupedSubsetFromStart = await measureMs ( `load iterate groupedByTeam subset from start (${ LOAD_SUBSET_ITERATION_ROW_COUNT } rows)` , async ( ) => {
838+ return await sql . unsafe ( `
839+ SELECT *
840+ FROM (${ toQueryableSqlQuery ( groupedByTeam . listRowsInGroup ( {
841+ groupKey : expr ( `to_jsonb('beta'::text)` ) ,
842+ start : "start" ,
843+ end : "end" ,
844+ startInclusive : true ,
845+ endInclusive : true ,
846+ } ) ) } ) AS "rows"
847+ LIMIT ${ LOAD_SUBSET_ITERATION_ROW_COUNT }
848+ ` ) ;
849+ } ) ;
850+ expect ( groupedSubsetFromStart . elapsedMs ) . toBeLessThanOrEqual ( LOAD_SUBSET_ITERATION_MAX_MS ) ;
851+ expect ( groupedSubsetFromStart . result ) . toHaveLength ( LOAD_SUBSET_ITERATION_ROW_COUNT ) ;
821852 const sortedHighValueByTeam = declareSortTable ( {
822853 tableId : "load-prefilled-users-high-value-sorted" ,
823854 fromTable : filteredHighValue ,
@@ -845,6 +876,36 @@ describe.sequential("bulldozer db performance (real postgres)", () => {
845876 await runStatements ( sortedHighValueByTeam . init ( ) ) ;
846877 } ) ;
847878 expect ( sortInit . elapsedMs ) . toBeLessThan ( LOAD_SORT_TABLE_INIT_MAX_MS ) ;
879+ const sortedSubsetFromStart = await measureMs ( `load iterate sortedHighValueByTeam subset from start (${ LOAD_SUBSET_ITERATION_ROW_COUNT } rows)` , async ( ) => {
880+ return await sql . unsafe ( `
881+ SELECT *
882+ FROM (${ toQueryableSqlQuery ( sortedHighValueByTeam . listRowsInGroup ( {
883+ groupKey : expr ( `to_jsonb('beta'::text)` ) ,
884+ start : "start" ,
885+ end : expr ( `to_jsonb(719::int)` ) ,
886+ startInclusive : true ,
887+ endInclusive : true ,
888+ } ) ) } ) AS "rows"
889+ LIMIT ${ LOAD_SUBSET_ITERATION_ROW_COUNT }
890+ ` ) ;
891+ } ) ;
892+ expect ( sortedSubsetFromStart . elapsedMs ) . toBeLessThanOrEqual ( LOAD_SUBSET_ITERATION_MAX_MS ) ;
893+ expect ( sortedSubsetFromStart . result ) . toHaveLength ( LOAD_SUBSET_ITERATION_ROW_COUNT ) ;
894+ const sortedSubsetFromSortKey = await measureMs ( `load iterate sortedHighValueByTeam subset from sort-key cursor (${ LOAD_SUBSET_ITERATION_ROW_COUNT } rows)` , async ( ) => {
895+ return await sql . unsafe ( `
896+ SELECT *
897+ FROM (${ toQueryableSqlQuery ( sortedHighValueByTeam . listRowsInGroup ( {
898+ groupKey : expr ( `to_jsonb('beta'::text)` ) ,
899+ start : expr ( `to_jsonb(900::int)` ) ,
900+ end : expr ( `to_jsonb(919::int)` ) ,
901+ startInclusive : true ,
902+ endInclusive : true ,
903+ } ) ) } ) AS "rows"
904+ LIMIT ${ LOAD_SUBSET_ITERATION_ROW_COUNT }
905+ ` ) ;
906+ } ) ;
907+ expect ( sortedSubsetFromSortKey . elapsedMs ) . toBeLessThanOrEqual ( LOAD_SUBSET_ITERATION_MAX_MS ) ;
908+ expect ( sortedSubsetFromSortKey . result ) . toHaveLength ( LOAD_SUBSET_ITERATION_ROW_COUNT ) ;
848909 const lFoldInit = await measureMs ( "load init foldedHighValueByTeam" , async ( ) => {
849910 await runStatements ( foldedHighValueByTeam . init ( ) ) ;
850911 } ) ;
@@ -941,7 +1002,6 @@ describe.sequential("bulldozer db performance (real postgres)", () => {
9411002 } ,
9421003 } ,
9431004 ] ) ;
944-
9451005 const bulkDelete = await measureMs ( "load full table delete" , async ( ) => {
9461006 await runStatements ( table . delete ( ) ) ;
9471007 } ) ;
@@ -960,7 +1020,7 @@ describe.sequential("bulldozer db performance (real postgres)", () => {
9601020 ` ;
9611021 expect ( isInitializedRows [ 0 ] . initialized ) . toBe ( false ) ;
9621022
963- logLine ( `[bulldozer-perf] load thresholds(ms): prefill<=${ LOAD_PREFILL_MAX_MS } , baseCount<=${ LOAD_COUNT_QUERY_MAX_MS } , setRowAvg<=${ LOAD_SET_ROW_AVG_MAX_MS } over ${ LOAD_SET_ROW_AVG_ITERATIONS } , pointDelete<=${ LOAD_POINT_MUTATION_MAX_MS } , derivedInit<=${ LOAD_DERIVED_INIT_MAX_MS } , filterInit<=${ LOAD_FILTER_TABLE_INIT_MAX_MS } , sortInit<=${ LOAD_SORT_TABLE_INIT_MAX_MS } , lfoldInit<=${ LOAD_LFOLD_TABLE_INIT_MAX_MS } , leftJoinInit<=${ LOAD_LEFT_JOIN_TABLE_INIT_MAX_MS } , concatInit<=${ LOAD_CONCAT_TABLE_INIT_MAX_MS } , limitInit<=${ LOAD_LIMIT_TABLE_INIT_MAX_MS } , expandingInit<=${ LOAD_EXPANDING_INIT_MAX_MS } , derivedCount<=${ LOAD_DERIVED_COUNT_QUERY_MAX_MS } , filterCount<=${ LOAD_FILTER_TABLE_COUNT_QUERY_MAX_MS } , lfoldCount<=${ LOAD_LFOLD_TABLE_COUNT_QUERY_MAX_MS } , leftJoinCount<=${ LOAD_LEFT_JOIN_TABLE_COUNT_QUERY_MAX_MS } , concatCount<=${ LOAD_CONCAT_TABLE_COUNT_QUERY_MAX_MS } , limitCount<=${ LOAD_LIMIT_TABLE_COUNT_QUERY_MAX_MS } , expandingCount<=${ LOAD_EXPANDING_COUNT_QUERY_MAX_MS } , filteredQuery<=${ LOAD_FILTERED_QUERY_MAX_MS } , tableDelete<=${ LOAD_TABLE_DELETE_MAX_MS } ` ) ;
964- } , 180_000 ) ;
1023+ logLine ( `[bulldozer-perf] load thresholds(ms): prefill<=${ LOAD_PREFILL_MAX_MS } , baseCount<=${ LOAD_COUNT_QUERY_MAX_MS } , setRowAvg<=${ LOAD_SET_ROW_AVG_MAX_MS } over ${ LOAD_SET_ROW_AVG_ITERATIONS } , pointDelete<=${ LOAD_POINT_MUTATION_MAX_MS } , onlineMutation<=${ LOAD_ONLINE_MUTATION_MAX_MS } , subsetIteration<=${ LOAD_SUBSET_ITERATION_MAX_MS } for ${ LOAD_SUBSET_ITERATION_ROW_COUNT } rows, derivedInit<=${ LOAD_DERIVED_INIT_MAX_MS } , filterInit<=${ LOAD_FILTER_TABLE_INIT_MAX_MS } , sortInit<=${ LOAD_SORT_TABLE_INIT_MAX_MS } , lfoldInit<=${ LOAD_LFOLD_TABLE_INIT_MAX_MS } , leftJoinInit<=${ LOAD_LEFT_JOIN_TABLE_INIT_MAX_MS } , concatInit<=${ LOAD_CONCAT_TABLE_INIT_MAX_MS } , limitInit<=${ LOAD_LIMIT_TABLE_INIT_MAX_MS } , expandingInit<=${ LOAD_EXPANDING_INIT_MAX_MS } , derivedCount<=${ LOAD_DERIVED_COUNT_QUERY_MAX_MS } , filterCount<=${ LOAD_FILTER_TABLE_COUNT_QUERY_MAX_MS } , lfoldCount<=${ LOAD_LFOLD_TABLE_COUNT_QUERY_MAX_MS } , leftJoinCount<=${ LOAD_LEFT_JOIN_TABLE_COUNT_QUERY_MAX_MS } , concatCount<=${ LOAD_CONCAT_TABLE_COUNT_QUERY_MAX_MS } , limitCount<=${ LOAD_LIMIT_TABLE_COUNT_QUERY_MAX_MS } , expandingCount<=${ LOAD_EXPANDING_COUNT_QUERY_MAX_MS } , filteredQuery<=${ LOAD_FILTERED_QUERY_MAX_MS } , tableDelete<=${ LOAD_TABLE_DELETE_MAX_MS } ` ) ;
1024+ } , 300_000 ) ;
9651025} ) ;
9661026
0 commit comments