parent
ecea2852f6
commit
c3d06df00a
weghting_n_cutting_the_tree
|
@ -1,3 +1,3 @@
|
||||||
## Алгоритм кумулятивного взвешивания асинхронного дерева
|
## [](https://drone.tiburon.su/TEMPLATES/tests) Алгоритм кумулятивного взвешивания и нарезки.
|
||||||
|
|
||||||
Стояла задача передавать огромное JSON дерево, которое целиком не пролезало в nginx. Исходя из предусловия, что дерево может быть сколь угодно большого размера, не стали полагаться на увеличение лимита и/или применение сжатия, было принято решение искать способ нарезать его на поддеревья, передать частями и на месте собрать.
|
Стояла задача передавать огромное JSON дерево, которое целиком не пролезало в nginx. Исходя из предусловия, что дерево может быть сколь угодно большого размера, не стали полагаться на увеличение лимита и/или применение сжатия, было принято решение искать способ нарезать его на поддеревья, передать частями и на месте собрать.
|
|
@ -0,0 +1,30 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Children []*Node `json:"children"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WeightedNode struct {
|
||||||
|
node *Node
|
||||||
|
parent *Node
|
||||||
|
children []*Node
|
||||||
|
weight uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubTree struct {
|
||||||
|
path string
|
||||||
|
tree *Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (root *Node) getNodeWeight() uint16 {
|
||||||
|
nodeBytes, _ := json.Marshal(&Node{
|
||||||
|
ID: root.ID,
|
||||||
|
Name: root.Name,
|
||||||
|
Children: []*Node{},
|
||||||
|
})
|
||||||
|
return uint16(len(nodeBytes))
|
||||||
|
}
|
|
@ -1,24 +1,10 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"maps"
|
"maps"
|
||||||
"tests/weghting_the_tree/dll"
|
"tests/weghting_n_cutting_the_tree/dll"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Node struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Children []*Node `json:"children"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WeightedNode struct {
|
|
||||||
node *Node
|
|
||||||
parent *Node
|
|
||||||
children []*Node
|
|
||||||
weight uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
func (root *Node) WeightingTreeWithRecursion(parent *Node) map[string]*WeightedNode {
|
func (root *Node) WeightingTreeWithRecursion(parent *Node) map[string]*WeightedNode {
|
||||||
weightedNode := &Node{
|
weightedNode := &Node{
|
||||||
ID: root.ID,
|
ID: root.ID,
|
||||||
|
@ -118,16 +104,6 @@ func (root *Node) WeightingTreeWithDLL() map[string]*WeightedNode {
|
||||||
return counter
|
return counter
|
||||||
}
|
}
|
||||||
|
|
||||||
//func DecomposeTree(tree map[string]*WeightedNode, limit int) ([]SubTree, error) {
|
func DecomposeTree(tree map[string]*WeightedNode, threshold int) ([]SubTree, error) {
|
||||||
//
|
return []SubTree{{path: "/", tree: tree["root"].node}}, nil
|
||||||
// return nil, nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (root *Node) getNodeWeight() uint16 {
|
|
||||||
nodeBytes, _ := json.Marshal(&Node{
|
|
||||||
ID: root.ID,
|
|
||||||
Name: root.Name,
|
|
||||||
Children: []*Node{},
|
|
||||||
})
|
|
||||||
return uint16(len(nodeBytes))
|
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -33,6 +34,31 @@ func TestNode_WeighingTreeAllAlgo(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecomposeTree(t *testing.T){
|
||||||
|
for name, tt := range map[string]struct{
|
||||||
|
inputTree map[string]*WeightedNode
|
||||||
|
inputThreshold int
|
||||||
|
outputParts []SubTree
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
"Normal":{
|
||||||
|
inputTree: smallTree.Tree,
|
||||||
|
inputThreshold: smallTree.Threshold,
|
||||||
|
outputParts: smallTree.Parts,
|
||||||
|
},
|
||||||
|
}{
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
result, err := DecomposeTree(tt.inputTree, tt.inputThreshold)
|
||||||
|
if tt.err == "" {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.ElementsMatch(t, result, tt.outputParts)
|
||||||
|
} else {
|
||||||
|
require.EqualError(t, err, tt.err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Benchmark(b *testing.B) {
|
func Benchmark(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
|
@ -42,3 +42,30 @@ func getTestTree(branches, depth int, parent *Node) TestTree {
|
||||||
}
|
}
|
||||||
return tree
|
return tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testDecomposingData struct {
|
||||||
|
Tree map[string]*WeightedNode
|
||||||
|
Threshold int
|
||||||
|
Parts []SubTree
|
||||||
|
}
|
||||||
|
|
||||||
|
var smallTree = testDecomposingData{
|
||||||
|
Tree: map[string]*WeightedNode{
|
||||||
|
"root": {
|
||||||
|
node: &Node{
|
||||||
|
ID: "root",
|
||||||
|
Name: "root",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Threshold: 2,
|
||||||
|
Parts: []SubTree{
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
tree: &Node{
|
||||||
|
ID: "root",
|
||||||
|
Name: "root",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
Loading…
Reference in New Issue