diff --git a/server/go.mod b/server/go.mod index 7c63f9d8d9e..549cf6f4754 100644 --- a/server/go.mod +++ b/server/go.mod @@ -40,7 +40,7 @@ require ( github.com/cornelk/hashmap v1.0.8 github.com/deckarep/golang-set v1.8.0 github.com/deckarep/golang-set/v2 v2.1.0 - github.com/deepflowio/deepflow/message v0.0.0-20240725065348-535fb6f1efdc + github.com/deepflowio/deepflow/message v0.0.0-20240911122335-79881b9ea7c2 github.com/deepflowio/deepflow/server/controller/cloud/kubernetes_gather/expand v0.0.0-00010101000000-000000000000 github.com/deepflowio/deepflow/server/controller/cloud/platform v0.0.0-00010101000000-000000000000 github.com/deepflowio/deepflow/server/controller/cloud/tencent/expand v0.0.0-00010101000000-000000000000 diff --git a/server/go.sum b/server/go.sum index 13be41a0c90..e2d6584cd73 100644 --- a/server/go.sum +++ b/server/go.sum @@ -167,8 +167,8 @@ github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsP github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/deepflowio/deepflow/message v0.0.0-20240725065348-535fb6f1efdc h1:B5hQ+ItZ4+dy4APMWZQeSV187j4dzDsxkAJfuEg1BLA= -github.com/deepflowio/deepflow/message v0.0.0-20240725065348-535fb6f1efdc/go.mod h1:e+1lUMMlycCvFRKvlwt/y/0vxJnF8wVss3GyR1ARXY0= +github.com/deepflowio/deepflow/message v0.0.0-20240911122335-79881b9ea7c2 h1:DVZBh0+UJMs2dWqpOELUpXjGdcitJ9HPGrfeBJ4NQsE= +github.com/deepflowio/deepflow/message v0.0.0-20240911122335-79881b9ea7c2/go.mod h1:e+1lUMMlycCvFRKvlwt/y/0vxJnF8wVss3GyR1ARXY0= github.com/deepflowio/tempopb v0.0.0-20230215110519-15853baf3a79 h1:erRwXyZiUZxxZX/Q1QHesZXgxjiunZUFy+ggCRimkD4= github.com/deepflowio/tempopb v0.0.0-20230215110519-15853baf3a79/go.mod h1:h2rkZ319TExIUGuK8a2dlcGd8qc6wdhsrcpXWaJQaQE= github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= diff --git a/server/querier/profile/model/model.go b/server/querier/profile/model/model.go index 8871b3cbc78..4edc2ff310d 100644 --- a/server/querier/profile/model/model.go +++ b/server/querier/profile/model/model.go @@ -43,6 +43,7 @@ type ProfileTreeNode struct { ParentNodeID int SelfValue int TotalValue int + Depth int } type Debug struct { diff --git a/server/querier/profile/service/profile.go b/server/querier/profile/service/profile.go index f54b9e83092..9c89283ee08 100644 --- a/server/querier/profile/service/profile.go +++ b/server/querier/profile/service/profile.go @@ -236,14 +236,53 @@ func GenerateProfile(args model.Profile, cfg *config.QuerierConfig, where string for i := range result.FunctionValues.Values { result.FunctionValues.Values[i] = []int{0, 0} } + result.NodeValues.Values = make([][]int, 0, len(nodes)) - for _, node := range nodes { + // 0.1% + valueThreshold := nodes[0].TotalValue / 1000 + depthThreshold := 12 + + // 先计算下 depth 和 FunctionValues 裁剪会修改node的数据 + for i, node := range nodes { locationID := node.LocationID result.FunctionValues.Values[locationID][0] += node.SelfValue result.FunctionValues.Values[locationID][1] += node.TotalValue - result.NodeValues.Values = append(result.NodeValues.Values, []int{locationID, node.ParentNodeID, node.SelfValue, node.TotalValue}) + updateDepth(nodes, i) + } + + // 获取需要删除的 node 数据的 id,即 下标 + deleteNodeIDs := []int{} + for i, node := range nodes { + if node.TotalValue >= valueThreshold || node.Depth <= depthThreshold { + continue + } + if node.ParentNodeID >= 0 { + nodes[node.ParentNodeID].SelfValue = nodes[node.ParentNodeID].SelfValue + node.TotalValue + } + deleteNodeIDs = append(deleteNodeIDs, i) + } + + // 获取删除node后的下表映射,用于更新ParentNodeID + mapping := getMapping(len(nodes), deleteNodeIDs) + + // 只返回符合条件的 node 数据 + maxDepth := 0 + for _, node := range nodes { + if node.TotalValue >= valueThreshold || node.Depth <= depthThreshold { + parentNodeID := node.ParentNodeID + if node.ParentNodeID != -1 { + parentNodeID = mapping[node.ParentNodeID] + } + result.NodeValues.Values = append(result.NodeValues.Values, []int{node.LocationID, parentNodeID, node.SelfValue, node.TotalValue}) + } + + if node.Depth > maxDepth { + maxDepth = node.Depth + } } + log.Infof("total nodes len=%d,total value is %d, valueThreshold is %d, valid node len=%d, maxDepth=%d", len(nodes), nodes[0].TotalValue, valueThreshold, len(result.NodeValues.Values), maxDepth) + result.Functions = locations locationTypes := GetLocationType(locations, result.FunctionValues.Values, args.ProfileEventType) result.FunctionTypes = locationTypes @@ -256,6 +295,16 @@ func GenerateProfile(args model.Profile, cfg *config.QuerierConfig, where string return } +func updateDepth(nodes []model.ProfileTreeNode, thisNodeID int) { + thisNode := &nodes[thisNodeID] + depth := 1 + for thisNode.ParentNodeID >= 0 { + depth++ + thisNode = &nodes[thisNode.ParentNodeID] + } + nodes[thisNodeID].Depth = depth +} + func newProfileTreeNode(locationID, selfValue, totalValue int) model.ProfileTreeNode { node := model.ProfileTreeNode{} node.LocationID = locationID @@ -275,7 +324,6 @@ func updateAllParentNodes(nodes []model.ProfileTreeNode, thisNodeID, selfValue, thisNode = &nodes[thisNode.ParentNodeID] thisNode.TotalValue += totalValue } - } func CutKernelFunction(profileLocationByteSlice []byte, maxKernelStackDepth int, sep string) ([]byte, bool) { @@ -343,3 +391,22 @@ func GetLocationType(locations []string, locationValues [][]int, profileEventTyp } return locationTypes } + +func getMapping(arrLen int, indicesToRemove []int) map[int]int { + removed := make(map[int]struct{}) + for _, index := range indicesToRemove { + removed[index] = struct{}{} + } + + mapping := make(map[int]int) + newIndex := 0 + + for i := 0; i < arrLen; i++ { + if _, found := removed[i]; !found { + mapping[i] = newIndex + newIndex++ + } + } + + return mapping +}