@@ -54,7 +54,6 @@ import type {
5454 IndexIntoStackTable ,
5555 IndexIntoResourceTable ,
5656 IndexIntoNativeSymbolTable ,
57- IndexIntoDeduplicatedCallNodeTable ,
5857 DeduplicatedCallNodeInfo ,
5958 ThreadIndex ,
6059 Category ,
@@ -1219,58 +1218,127 @@ export function getTimingsForCallNodeIndex(
12191218 return { forPath : pathTimings , rootTime } ;
12201219}
12211220
1221+ function _hash32 ( val : number ) : number {
1222+ const rotated1 = val << 5 ;
1223+ const rotated2 = val >> 27 ;
1224+ const rotated = rotated1 | rotated2 ;
1225+ const xored = rotated ^ val ;
1226+ return ( xored * 0x9e_37_79_b9 ) | 0 ;
1227+ }
1228+
12221229export function computeDeduplicatedCallNodeInfo (
12231230 callNodeInfo : CallNodeInfo
12241231) : DeduplicatedCallNodeInfo {
12251232 const callNodeTable = callNodeInfo . getNonInvertedCallNodeTable ( ) ;
12261233
1227- let len = 0 ;
1228- const prefixCol : IndexIntoDeduplicatedCallNodeTable [ ] = [ ] ;
1229- const funcCol : IndexIntoFuncTable [ ] = [ ] ;
1230-
12311234 const callNodeCount = callNodeTable . length ;
1235+ const funcCol = callNodeTable . func ;
1236+ const prefixCol = callNodeTable . prefix ;
1237+ const newPrefixCol = new Int32Array ( callNodeCount ) ;
1238+ const bloomBitsCol1 = new Int32Array ( callNodeCount ) ;
1239+ const bloomBitsCol2 = new Int32Array ( callNodeCount ) ;
1240+ const bloomBitsCol3 = new Int32Array ( callNodeCount ) ;
1241+ const bloomBitsCol4 = new Int32Array ( callNodeCount ) ;
1242+
12321243 const callNodeIndexToDeduplicatedCallNodeIndex = new Uint32Array (
12331244 callNodeCount
12341245 ) ;
12351246
1247+ const funcBloomBits = new Int32Array ( 4 ) ;
12361248 for ( let callNodeIndex = 0 ; callNodeIndex < callNodeCount ; callNodeIndex ++ ) {
1237- const originalPrefix = callNodeTable . prefix [ callNodeIndex ] ;
1238- const func = callNodeTable . func [ callNodeIndex ] ;
1239- let prefix = - 1 ;
1240- if ( originalPrefix !== - 1 ) {
1241- prefix = callNodeIndexToDeduplicatedCallNodeIndex [ originalPrefix ] ;
1242-
1243- // Check if `func` is present in the prefix's call path.
1244- let prefixHasFunc = false ;
1245- for (
1246- let dedupAnc = prefix ;
1247- dedupAnc !== - 1 ;
1248- dedupAnc = prefixCol [ dedupAnc ]
1249- ) {
1250- if ( funcCol [ dedupAnc ] === func ) {
1251- prefixHasFunc = true ;
1252- break ;
1249+ const prefix = prefixCol [ callNodeIndex ] ;
1250+ const func = funcCol [ callNodeIndex ] ;
1251+
1252+ const funcHash = _hash32 ( func ) ;
1253+ const funcHashBitIndex1 = funcHash % 32 ;
1254+ const funcHashBitIndex2 = ( funcHash >> 5 ) % 32 ;
1255+ // const funcHashBitIndex3 = (funcHash >> 10) % 32;
1256+ const funcHashBit1 = 1 << funcHashBitIndex1 ;
1257+ const funcHashBit2 = 1 << funcHashBitIndex2 ;
1258+ // const funcHashBit3 = 1 << funcHashBitIndex3;
1259+ const funcBitDistributor1 = ( funcHash >> 15 ) & 0b11 ;
1260+ const funcBitDistributor2 = ( funcHash >> 17 ) & 0b11 ;
1261+ // const funcBitDistributor3 = (funcHash >> 19) & 0b11;
1262+
1263+ funcBloomBits [ 0 ] = 0 ;
1264+ funcBloomBits [ 1 ] = 0 ;
1265+ funcBloomBits [ 2 ] = 0 ;
1266+ funcBloomBits [ 3 ] = 0 ;
1267+ funcBloomBits [ funcBitDistributor1 ] |= funcHashBit1 ;
1268+ funcBloomBits [ funcBitDistributor2 ] |= funcHashBit2 ;
1269+ // funcBloomBits[funcBitDistributor3] |= funcHashBit3;
1270+
1271+ const funcBloomBits1 = funcBloomBits [ 0 ] ;
1272+ const funcBloomBits2 = funcBloomBits [ 1 ] ;
1273+ const funcBloomBits3 = funcBloomBits [ 2 ] ;
1274+ const funcBloomBits4 = funcBloomBits [ 3 ] ;
1275+
1276+ let prefixBloomBits1 = 0 ;
1277+ let prefixBloomBits2 = 0 ;
1278+ let prefixBloomBits3 = 0 ;
1279+ let prefixBloomBits4 = 0 ;
1280+ let newPrefix = - 1 ;
1281+ if ( prefix !== - 1 ) {
1282+ newPrefix = callNodeIndexToDeduplicatedCallNodeIndex [ prefix ] ;
1283+ prefixBloomBits1 = bloomBitsCol1 [ newPrefix ] ;
1284+ prefixBloomBits2 = bloomBitsCol2 [ newPrefix ] ;
1285+ prefixBloomBits3 = bloomBitsCol3 [ newPrefix ] ;
1286+ prefixBloomBits4 = bloomBitsCol4 [ newPrefix ] ;
1287+
1288+ // Check if `func` is present in the newPrefix's call path.
1289+ let funcIsAlreadyPresentInPrefix = false ;
1290+
1291+ const hashMatched =
1292+ ( prefixBloomBits1 & funcBloomBits1 ) === funcBloomBits1 &&
1293+ ( prefixBloomBits2 & funcBloomBits2 ) === funcBloomBits2 &&
1294+ ( prefixBloomBits3 & funcBloomBits3 ) === funcBloomBits3 &&
1295+ ( prefixBloomBits4 & funcBloomBits4 ) === funcBloomBits4 ;
1296+ if ( hashMatched ) {
1297+ let dedupIndex = newPrefix ;
1298+ for ( let j = 0 ; ; j ++ ) {
1299+ if ( funcCol [ dedupIndex ] === func ) {
1300+ funcIsAlreadyPresentInPrefix = true ;
1301+ break ;
1302+ }
1303+ dedupIndex = newPrefixCol [ dedupIndex ] ;
1304+ if (
1305+ dedupIndex === - 1 ||
1306+ ( j % 2 === 0 &&
1307+ ( ( bloomBitsCol1 [ dedupIndex ] & funcBloomBits1 ) !==
1308+ funcBloomBits1 ||
1309+ ( bloomBitsCol2 [ dedupIndex ] & funcBloomBits2 ) !==
1310+ funcBloomBits2 ||
1311+ ( bloomBitsCol3 [ dedupIndex ] & funcBloomBits3 ) !==
1312+ funcBloomBits3 ||
1313+ ( bloomBitsCol4 [ dedupIndex ] & funcBloomBits4 ) !==
1314+ funcBloomBits4 ) )
1315+ ) {
1316+ break ;
1317+ }
12531318 }
12541319 }
1255-
1256- if ( prefixHasFunc ) {
1320+ if ( funcIsAlreadyPresentInPrefix ) {
12571321 // Drop this node.
1258- callNodeIndexToDeduplicatedCallNodeIndex [ callNodeIndex ] = prefix ;
1322+ callNodeIndexToDeduplicatedCallNodeIndex [ callNodeIndex ] = newPrefix ;
12591323 continue ;
12601324 }
12611325 }
12621326
12631327 // Create a node in the deduplicated call node table.
1264- const newIndex = len ++ ;
1265- prefixCol [ newIndex ] = prefix ;
1266- funcCol [ newIndex ] = func ;
1267- callNodeIndexToDeduplicatedCallNodeIndex [ callNodeIndex ] = newIndex ;
1328+ newPrefixCol [ callNodeIndex ] = newPrefix ;
1329+ bloomBitsCol1 [ callNodeIndex ] = prefixBloomBits1 | funcBloomBits1 ;
1330+ bloomBitsCol2 [ callNodeIndex ] = prefixBloomBits2 | funcBloomBits2 ;
1331+ bloomBitsCol3 [ callNodeIndex ] = prefixBloomBits3 | funcBloomBits3 ;
1332+ bloomBitsCol4 [ callNodeIndex ] = prefixBloomBits4 | funcBloomBits4 ;
1333+ callNodeIndexToDeduplicatedCallNodeIndex [ callNodeIndex ] = callNodeIndex ;
12681334 }
12691335
1336+ // console.log({bloomBitsCol1: bloomBitsCol1.slice(0, 1000).map((num) => num.toString(2)) });
1337+
12701338 const deduplicatedCallNodeTable = {
1271- length : len ,
1272- prefix : new Int32Array ( prefixCol ) ,
1273- func : new Uint32Array ( funcCol ) ,
1339+ length : callNodeCount ,
1340+ prefix : newPrefixCol ,
1341+ func : funcCol ,
12741342 } ;
12751343
12761344 return {
0 commit comments