@@ -267,6 +267,10 @@ const keyFromEnvContentKey = (contentKey: ContentKey): string =>
267
267
const keyFromOptionContentKey = ( contentKey : ContentKey ) : string =>
268
268
contentKey . slice ( 'option:' . length ) ;
269
269
270
+ // This constant is chosen by local profiling the time to serialise n nodes and tuning until an average time of ~50 ms per blob.
271
+ // The goal is to free up the event loop periodically to allow interruption by the user.
272
+ const NODES_PER_BLOB = 2 ** 14 ;
273
+
270
274
export class RequestGraph extends ContentGraph <
271
275
RequestGraphNode ,
272
276
RequestGraphEdgeType ,
@@ -283,6 +287,7 @@ export class RequestGraph extends ContentGraph<
283
287
invalidateOnBuildNodeIds: Set < NodeId > = new Set ( ) ;
284
288
cachedRequestChunks: Set < number > = new Set ( ) ;
285
289
configKeyNodes: Map < ProjectPath , Set < NodeId >> = new Map ( ) ;
290
+ nodesPerBlob: number = NODES_PER_BLOB ;
286
291
287
292
// $FlowFixMe[prop-missing]
288
293
static deserialize ( opts : RequestGraphOpts ) : RequestGraph {
@@ -1032,14 +1037,10 @@ export class RequestGraph extends ContentGraph<
1032
1037
}
1033
1038
1034
1039
removeCachedRequestChunkForNode ( nodeId : number ) : void {
1035
- this. cachedRequestChunks . delete ( Math . floor ( nodeId / NODES_PER_BLOB ) ) ;
1040
+ this. cachedRequestChunks . delete ( Math . floor ( nodeId / this . nodesPerBlob ) ) ;
1036
1041
}
1037
1042
}
1038
1043
1039
- // This constant is chosen by local profiling the time to serialise n nodes and tuning until an average time of ~50 ms per blob.
1040
- // The goal is to free up the event loop periodically to allow interruption by the user.
1041
- const NODES_PER_BLOB = 2 ** 14 ;
1042
-
1043
1044
export default class RequestTracker {
1044
1045
graph : RequestGraph ;
1045
1046
farm : WorkerFarm ;
@@ -1427,17 +1428,30 @@ export default class RequestTracker {
1427
1428
}
1428
1429
}
1429
1430
1430
- for ( let i = 0 ; i * NODES_PER_BLOB < cacheableNodes . length ; i += 1 ) {
1431
+ let nodeCountsPerBlob = [ ] ;
1432
+
1433
+ for (
1434
+ let i = 0 ;
1435
+ i * this . graph . nodesPerBlob < cacheableNodes . length ;
1436
+ i += 1
1437
+ ) {
1438
+ let nodesStartIndex = i * this . graph . nodesPerBlob ;
1439
+ let nodesEndIndex = Math . min (
1440
+ ( i + 1 ) * this . graph . nodesPerBlob ,
1441
+ cacheableNodes . length ,
1442
+ ) ;
1443
+
1444
+ nodeCountsPerBlob . push ( nodesEndIndex - nodesStartIndex ) ;
1445
+
1431
1446
if ( ! this . graph . hasCachedRequestChunk ( i ) ) {
1432
1447
// We assume the request graph nodes are immutable and won't change
1448
+ let nodesToCache = cacheableNodes . slice ( nodesStartIndex , nodesEndIndex ) ;
1449
+
1433
1450
queue
1434
1451
. add ( ( ) =>
1435
1452
serialiseAndSet (
1436
1453
getRequestGraphNodeKey ( i , cacheKey ) ,
1437
- cacheableNodes . slice (
1438
- i * NODES_PER_BLOB ,
1439
- ( i + 1 ) * NODES_PER_BLOB ,
1440
- ) ,
1454
+ nodesToCache ,
1441
1455
) . then ( ( ) => {
1442
1456
// Succeeded in writing to disk, save that we have completed this chunk
1443
1457
this . graph . setCachedRequestChunk ( i ) ;
@@ -1455,6 +1469,7 @@ export default class RequestTracker {
1455
1469
// Set the request graph after the queue is flushed to avoid writing an invalid state
1456
1470
await serialiseAndSet ( requestGraphKey , {
1457
1471
...serialisedGraph ,
1472
+ nodeCountsPerBlob,
1458
1473
nodes : undefined ,
1459
1474
} ) ;
1460
1475
@@ -1523,19 +1538,24 @@ export async function readAndDeserializeRequestGraph(
1523
1538
return deserialize ( buffer ) ;
1524
1539
} ;
1525
1540
1526
- let i = 0 ;
1527
- let nodePromises = [ ] ;
1528
- while ( await cache . hasLargeBlob ( getRequestGraphNodeKey ( i , cacheKey ) ) ) {
1529
- nodePromises . push ( getAndDeserialize ( getRequestGraphNodeKey ( i , cacheKey ) ) ) ;
1530
- i += 1 ;
1531
- }
1532
-
1533
1541
let serializedRequestGraph = await getAndDeserialize ( requestGraphKey ) ;
1534
1542
1543
+ let nodePromises = serializedRequestGraph . nodeCountsPerBlob . map (
1544
+ async ( nodesCount , i ) => {
1545
+ let nodes = await getAndDeserialize ( getRequestGraphNodeKey ( i , cacheKey ) ) ;
1546
+ invariant . equal (
1547
+ nodes . length ,
1548
+ nodesCount ,
1549
+ 'RequestTracker node chunk: invalid node count' ,
1550
+ ) ;
1551
+ return nodes ;
1552
+ } ,
1553
+ ) ;
1554
+
1535
1555
return {
1536
1556
requestGraph : RequestGraph . deserialize ( {
1537
1557
...serializedRequestGraph ,
1538
- nodes : ( await Promise . all ( nodePromises ) ) . flatMap ( nodeChunk => nodeChunk ) ,
1558
+ nodes : ( await Promise . all ( nodePromises ) ) . flat ( ) ,
1539
1559
} ) ,
1540
1560
// This is used inside parcel query for `.inspectCache`
1541
1561
bufferLength,
0 commit comments