Закончил бенчмарки
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
9b947bf937
commit
c6d33c500d
|
@ -17,19 +17,19 @@ type WeightedNode struct {
|
|||
weight uint16
|
||||
}
|
||||
|
||||
func (root Node) WeighingTreeWithRecursion() map[string]uint16 {
|
||||
weight := getNodeWeight(root.ID, root.Name)
|
||||
func (root Node) WeightingTreeWithRecursion() map[string]uint16 {
|
||||
weight := root.getNodeWeight()
|
||||
var res = make(map[string]uint16)
|
||||
for _, v := range root.Children {
|
||||
maps.Copy(res, v.WeighingTreeWithRecursion()) // Т.е. в go нет оптимизации хвостовой рекурсии, это породит неимоверное кол-во аллокаций.
|
||||
maps.Copy(res, v.WeightingTreeWithRecursion()) // Т.е. в go нет оптимизации хвостовой рекурсии, это породит неимоверное кол-во аллокаций.
|
||||
weight = weight + res[v.ID]
|
||||
}
|
||||
res[root.ID] = weight
|
||||
return res
|
||||
}
|
||||
|
||||
func (root Node) WeighingTreeWithStack() map[string]uint16 {
|
||||
weight := getNodeWeight(root.ID, root.Name)
|
||||
func (root Node) WeightingTreeWithStack() map[string]uint16 {
|
||||
weight := root.getNodeWeight()
|
||||
counter := map[string]*WeightedNode{root.ID: {
|
||||
weight: weight,
|
||||
}}
|
||||
|
@ -38,7 +38,7 @@ func (root Node) WeighingTreeWithStack() map[string]uint16 {
|
|||
current := stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
|
||||
nodeWeight := getNodeWeight(current.ID, current.Name)
|
||||
nodeWeight := current.getNodeWeight()
|
||||
counter[current.ID].weight = nodeWeight
|
||||
// Прибавляем вес всем родительским нодам до корня
|
||||
parentID := counter[current.ID].parent
|
||||
|
@ -68,7 +68,7 @@ func (root Node) WeighingTreeWithStack() map[string]uint16 {
|
|||
}
|
||||
|
||||
func (root Node) WeightingTreeWithDLL() map[string]uint16 {
|
||||
weight := getNodeWeight(root.ID, root.Name)
|
||||
weight := root.getNodeWeight()
|
||||
counter := map[string]*WeightedNode{root.ID: {
|
||||
weight: weight,
|
||||
}}
|
||||
|
@ -79,7 +79,7 @@ func (root Node) WeightingTreeWithDLL() map[string]uint16 {
|
|||
current := dllist.Front()
|
||||
dllist.Remove(current)
|
||||
|
||||
nodeWeight := getNodeWeight(current.Value.(Node).ID, current.Value.(Node).Name)
|
||||
nodeWeight := current.Value.(Node).getNodeWeight()
|
||||
counter[current.Value.(Node).ID].weight = nodeWeight
|
||||
// Прибавляем вес всем родительским нодам до корня
|
||||
parentID := counter[current.Value.(Node).ID].parent
|
||||
|
@ -113,10 +113,10 @@ func (root Node) DecomposeTree(weights map[string]uint16, limit int) ([]*Node, e
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func getNodeWeight(id string, name string) uint16 {
|
||||
func (n Node) getNodeWeight() uint16 {
|
||||
nodeBytes, _ := json.Marshal(Node{
|
||||
ID: id,
|
||||
Name: name,
|
||||
ID: n.ID,
|
||||
Name: n.Name,
|
||||
})
|
||||
return uint16(len(nodeBytes))
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func BenchmarkNode_WeighingSmallOrdinaryTreeWithRecursion(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
assert.EqualValues(b, testOrdinaryVFS.Weghts, testOrdinaryVFS.Tree.WeighingTreeWithRecursion())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNode_WeighingSmallOrdinaryTreeWithStack(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
assert.EqualValues(b, testOrdinaryVFS.Weghts, testOrdinaryVFS.Tree.WeighingTreeWithStack())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNode_WeighingSmallOrdinaryTreeWithDLL(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
assert.EqualValues(b, testOrdinaryVFS.Weghts, testOrdinaryVFS.Tree.WeightingTreeWithDLL())
|
||||
}
|
||||
}
|
|
@ -1,29 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func TestNode_WeighingTreeAllAlgo(t *testing.T) {
|
||||
for name,tt := range map[string]struct{
|
||||
input Node
|
||||
output map[string]uint16
|
||||
}{
|
||||
"Ordinary VFS tree":{
|
||||
input:testOrdinaryVFS.Tree,
|
||||
output: testOrdinaryVFS.Weghts,
|
||||
},
|
||||
"VFS in the form of a pathological tree":{
|
||||
input: testPathologicalTree.Tree,
|
||||
output: testPathologicalTree.Weghts,
|
||||
},
|
||||
for name,tt := range map[string]TestTree{
|
||||
"Ordinary VFS tree": getTestTree(4, 4),
|
||||
"VFS in the form of a pathological tree":getTestTree(1, 100),
|
||||
}{
|
||||
t.Run(name,func(t *testing.T) {
|
||||
assert.EqualValues(t, tt.output, tt.input.WeighingTreeWithRecursion())
|
||||
assert.EqualValues(t, tt.output, tt.input.WeighingTreeWithStack())
|
||||
assert.EqualValues(t, tt.output, tt.input.WeightingTreeWithDLL())
|
||||
assert.EqualValues(t, tt.Weights, tt.Tree.WeightingTreeWithRecursion())
|
||||
assert.EqualValues(t, tt.Weights, tt.Tree.WeightingTreeWithStack())
|
||||
assert.EqualValues(t, tt.Weights, tt.Tree.WeightingTreeWithDLL())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -31,3 +23,42 @@ func TestNode_WeighingTreeAllAlgo(t *testing.T) {
|
|||
func TestNode_DecomposeTree(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func Benchmark(b *testing.B) {
|
||||
b.StopTimer()
|
||||
b.ResetTimer()
|
||||
for name,tt := range map[string]struct{
|
||||
branches int
|
||||
depth int
|
||||
}{
|
||||
"Small tree":{4, 4}, // 85 nodes,
|
||||
"Wide tree": {515, 3}, // 265'741 nodes,
|
||||
"Deep tree": {3, 12}, // 265'720 nodes,
|
||||
"Huge tree": {5, 10}, // 2'441'406 nodes,
|
||||
"Pathological tree": {1, 10000}, // 10'000 nodes,
|
||||
}{
|
||||
b.Run(name, func(b *testing.B) {
|
||||
tree := getTestTree(tt.branches, tt.depth)
|
||||
b.Cleanup(func() {
|
||||
tree = TestTree{nil, nil}
|
||||
})
|
||||
b.Run("Weighing with recursion", func(b *testing.B) {
|
||||
b.StartTimer()
|
||||
assert.EqualValues(b, tree.Weights, tree.Tree.WeightingTreeWithRecursion())
|
||||
b.StopTimer()
|
||||
})
|
||||
b.Run("Weighting with stack", func(b *testing.B) {
|
||||
b.StartTimer()
|
||||
assert.EqualValues(b, tree.Weights, tree.Tree.WeightingTreeWithStack())
|
||||
b.StopTimer()
|
||||
})
|
||||
b.Run("Weighting with DLL", func(b *testing.B) {
|
||||
b.StartTimer()
|
||||
assert.EqualValues(b, tree.Weights, tree.Tree.WeightingTreeWithDLL())
|
||||
b.StopTimer()
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,227 +1,39 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"maps"
|
||||
)
|
||||
|
||||
type TestTree struct {
|
||||
Tree Node
|
||||
Weghts map[string]uint16
|
||||
Tree *Node
|
||||
Weights map[string]uint16
|
||||
}
|
||||
|
||||
var testOrdinaryVFS = TestTree{
|
||||
Tree: Node{
|
||||
ID: "node0",
|
||||
Name: "node0",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node01",
|
||||
Name: "node01",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node011",
|
||||
Name: "node011",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node012",
|
||||
Name: "node012",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node013",
|
||||
Name: "node013",
|
||||
Children: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "node02",
|
||||
Name: "node02",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node021",
|
||||
Name: "node021",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node022",
|
||||
Name: "node022",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node023",
|
||||
Name: "node023",
|
||||
Children: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "node03",
|
||||
Name: "node03",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node031",
|
||||
Name: "node031",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node0311",
|
||||
Name: "node0311",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node03111",
|
||||
Name: "node03111",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node03112",
|
||||
Name: "node03112",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node03113",
|
||||
Name: "node03113",
|
||||
Children: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "node0312",
|
||||
Name: "node0312",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node0313",
|
||||
Name: "node0313",
|
||||
Children: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "node032",
|
||||
Name: "node032",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node033",
|
||||
Name: "node033",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node0331",
|
||||
Name: "node0331",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node0332",
|
||||
Name: "node0332",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node03321",
|
||||
Name: "node03321",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node03322",
|
||||
Name: "node03322",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node03323",
|
||||
Name: "node03323",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node033231",
|
||||
Name: "node033231",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node033232",
|
||||
Name: "node033232",
|
||||
Children: nil,
|
||||
},
|
||||
{
|
||||
ID: "node033233",
|
||||
Name: "node033233",
|
||||
Children: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "node0333",
|
||||
Name: "node0333",
|
||||
Children: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Weghts: map[string]uint16{"node0": 1416, "node01": 194, "node011": 49, "node012": 49, "node013": 49, "node02": 194, "node021": 49, "node022": 49, "node023": 49, "node03": 983, "node031": 361, "node0311": 210, "node03111": 53, "node03112": 53, "node03113": 53, "node0312": 51, "node0313": 51, "node032": 49, "node033": 526, "node0331": 51, "node0332": 375, "node03321": 53, "node03322": 53, "node03323": 218, "node033231": 55, "node033232": 55, "node033233": 55, "node0333": 51},
|
||||
}
|
||||
func getTestTree(branches, depth int) TestTree {
|
||||
if depth == 0 {
|
||||
return TestTree{}
|
||||
}
|
||||
id := uuid.NewString()
|
||||
node := &Node{
|
||||
ID: id,
|
||||
Name: id,
|
||||
}
|
||||
tree := TestTree{
|
||||
Tree: node,
|
||||
Weights: map[string]uint16{id: node.getNodeWeight()},
|
||||
}
|
||||
|
||||
var testPathologicalTree = TestTree{
|
||||
Tree: Node{
|
||||
ID: "node0",
|
||||
Name: "node0",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node01",
|
||||
Name: "node01",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node012",
|
||||
Name: "node012",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node0123",
|
||||
Name: "node0123",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node01234",
|
||||
Name: "node01234",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node012345",
|
||||
Name: "node012345",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node0123456",
|
||||
Name: "node0123456",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node01234567",
|
||||
Name: "node01234567",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node012345678",
|
||||
Name: "node012345678",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node0123456789",
|
||||
Name: "node0123456789",
|
||||
Children: []*Node{
|
||||
{
|
||||
ID: "node0123456789A",
|
||||
Name: "node0123456789A",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Weghts: map[string]uint16{"node0": 605, "node01": 560, "node012": 513, "node0123": 464, "node01234": 413, "node012345": 360, "node0123456": 305, "node01234567": 248, "node012345678": 189, "node0123456789": 128, "node0123456789A": 65},
|
||||
for i := 0; i < branches; i++ {
|
||||
childTree := getTestTree(branches, depth-1)
|
||||
if childTree.Tree != nil {
|
||||
tree.Tree.Children = append(tree.Tree.Children, childTree.Tree)
|
||||
maps.Copy(tree.Weights, childTree.Weights)
|
||||
}
|
||||
}
|
||||
for _, child := range tree.Tree.Children {
|
||||
tree.Weights[id] = tree.Weights[id] + tree.Weights[child.ID]
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.21
|
|||
|
||||
require (
|
||||
github.com/codingsince1985/checksum v1.3.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/crypto v0.27.0
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -3,6 +3,8 @@ github.com/codingsince1985/checksum v1.3.0/go.mod h1:QfRskdtdWap+gJil8e5obw6I8/c
|
|||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
|
|
Loading…
Reference in New Issue