From e81b7e8feeb65f02b7fe0ad20793374147de55bc Mon Sep 17 00:00:00 2001 From: rleungx Date: Wed, 22 Aug 2018 20:22:33 +0800 Subject: [PATCH 1/2] add statistics for simulator --- cmd/simulator/main.go | 1 + pkg/faketikv/cases/add_nodes.go | 2 +- pkg/faketikv/cases/add_nodes_dynamic.go | 3 +- pkg/faketikv/cases/delete_nodes.go | 2 +- pkg/faketikv/drive.go | 5 + pkg/faketikv/raft.go | 14 ++- pkg/faketikv/statistics.go | 145 ++++++++++++++++++++++++ pkg/faketikv/task.go | 17 +++ 8 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 pkg/faketikv/statistics.go diff --git a/cmd/simulator/main.go b/cmd/simulator/main.go index bcededb28e4..c3639d0705d 100644 --- a/cmd/simulator/main.go +++ b/cmd/simulator/main.go @@ -174,6 +174,7 @@ EXIT: } fmt.Printf("%s [%s] total iteration: %d, time cost: %v\n", simResult, confName, driver.TickCount(), time.Since(start)) + driver.Print() if simResult != "OK" { os.Exit(1) diff --git a/pkg/faketikv/cases/add_nodes.go b/pkg/faketikv/cases/add_nodes.go index b17ab17a234..eb003252e19 100644 --- a/pkg/faketikv/cases/add_nodes.go +++ b/pkg/faketikv/cases/add_nodes.go @@ -63,8 +63,8 @@ func newAddNodes() *Conf { if regionCount > 390 || regionCount < 360 { res = false } - } + simutil.Logger.Infof("leader counts: %v", leaderCounts) simutil.Logger.Infof("region counts: %v", regionCounts) return res diff --git a/pkg/faketikv/cases/add_nodes_dynamic.go b/pkg/faketikv/cases/add_nodes_dynamic.go index 66f7e901a7a..0831b777c7f 100644 --- a/pkg/faketikv/cases/add_nodes_dynamic.go +++ b/pkg/faketikv/cases/add_nodes_dynamic.go @@ -28,6 +28,7 @@ func newAddNodesDynamic() *Conf { Status: metapb.StoreState_Up, Capacity: 1 * TB, Available: 900 * GB, + Version: "2.1.0", }) } @@ -80,8 +81,8 @@ func newAddNodesDynamic() *Conf { if regionCount > 390 || regionCount < 360 { res = false } - } + simutil.Logger.Infof("leader counts: %v", leaderCounts) simutil.Logger.Infof("region counts: %v", regionCounts) return res diff --git a/pkg/faketikv/cases/delete_nodes.go b/pkg/faketikv/cases/delete_nodes.go index d273e5767bd..2d29e812f4e 100644 --- a/pkg/faketikv/cases/delete_nodes.go +++ b/pkg/faketikv/cases/delete_nodes.go @@ -84,8 +84,8 @@ func newDeleteNodes() *Conf { if regionCount > 443 || regionCount < 413 { res = false } - } + simutil.Logger.Infof("leader counts: %v", leaderCounts) simutil.Logger.Infof("region counts: %v", regionCounts) return res diff --git a/pkg/faketikv/drive.go b/pkg/faketikv/drive.go index d0c45f2e5c7..f6453fb4980 100644 --- a/pkg/faketikv/drive.go +++ b/pkg/faketikv/drive.go @@ -124,6 +124,11 @@ func (d *Driver) Check() bool { return d.conf.Checker(d.raftEngine.regionsInfo) } +// Print prints the statistics of the scheduler. +func (d *Driver) Print() { + d.raftEngine.schedulerStats.Print() +} + // Stop stops all nodes. func (d *Driver) Stop() { for _, n := range d.clusterInfo.Nodes { diff --git a/pkg/faketikv/raft.go b/pkg/faketikv/raft.go index 3afdcd4779c..37152e50161 100644 --- a/pkg/faketikv/raft.go +++ b/pkg/faketikv/raft.go @@ -27,17 +27,19 @@ import ( // RaftEngine records all raft infomations. type RaftEngine struct { sync.RWMutex - regionsInfo *core.RegionsInfo - conn *Conn - regionchange map[uint64][]uint64 + regionsInfo *core.RegionsInfo + conn *Conn + regionchange map[uint64][]uint64 + schedulerStats *schedulerStatistics } // NewRaftEngine creates the initialized raft with the configuration. func NewRaftEngine(conf *cases.Conf, conn *Conn) (*RaftEngine, error) { r := &RaftEngine{ - regionsInfo: core.NewRegionsInfo(), - conn: conn, - regionchange: make(map[uint64][]uint64), + regionsInfo: core.NewRegionsInfo(), + conn: conn, + regionchange: make(map[uint64][]uint64), + schedulerStats: newSchedulerStatistics(), } splitKeys := generateKeys(len(conf.Regions) - 1) diff --git a/pkg/faketikv/statistics.go b/pkg/faketikv/statistics.go new file mode 100644 index 00000000000..91f9115831d --- /dev/null +++ b/pkg/faketikv/statistics.go @@ -0,0 +1,145 @@ +// Copyright 2018 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package faketikv + +import ( + "fmt" + "math" +) + +type taskStatistics struct { + addPeer map[uint64]int + removePeer map[uint64]int + addLearner map[uint64]int + promoteLeaner map[uint64]int + transferLeader map[uint64]map[uint64]int + mergeRegion int +} + +func newTaskStatistics() *taskStatistics { + return &taskStatistics{ + addPeer: make(map[uint64]int), + removePeer: make(map[uint64]int), + addLearner: make(map[uint64]int), + promoteLeaner: make(map[uint64]int), + transferLeader: make(map[uint64]map[uint64]int), + } +} + +func (t *taskStatistics) getStatistics() map[string]int { + stats := make(map[string]int) + addpeer := getSum(t.addPeer) + removePeer := getSum(t.removePeer) + addLearner := getSum(t.addLearner) + promoteLeaner := getSum(t.promoteLeaner) + + var transferLeader int + for _, to := range t.transferLeader { + for _, v := range to { + transferLeader += v + } + } + + stats["Add Peer (task)"] = addpeer + stats["Remove Peer (task)"] = removePeer + stats["Add Learner (task)"] = addLearner + stats["Promote Learner (task)"] = promoteLeaner + stats["Transfer Leader (task)"] = transferLeader + stats["Merge Region (task)"] = t.mergeRegion + + return stats +} + +type snapshotStatistics struct { + receive map[uint64]int + send map[uint64]int +} + +func newSnapshotStatistics() *snapshotStatistics { + return &snapshotStatistics{ + receive: make(map[uint64]int), + send: make(map[uint64]int), + } +} + +type schedulerStatistics struct { + taskStats *taskStatistics + snapshotStats *snapshotStatistics +} + +func newSchedulerStatistics() *schedulerStatistics { + return &schedulerStatistics{ + taskStats: newTaskStatistics(), + snapshotStats: newSnapshotStatistics(), + } +} + +func (s *snapshotStatistics) getStatistics() map[string]int { + maxSend := getMax(s.send) + maxReceive := getMax(s.receive) + minSend := getMin(s.send) + minReceive := getMin(s.receive) + + stats := make(map[string]int) + stats["Send Maximum (snapshot)"] = maxSend + stats["Receive Maximum (snapshot)"] = maxReceive + if minSend != math.MaxInt32 { + stats["Send Minimum (snapshot)"] = minSend + } + if minReceive != math.MaxInt32 { + stats["Receive Minimum (snapshot)"] = minReceive + } + + return stats +} + +// Print prints the statistics of the scheduler. +func (s *schedulerStatistics) Print() { + task := s.taskStats.getStatistics() + snap := s.snapshotStats.getStatistics() + for t, count := range task { + fmt.Println(t, count) + } + for s, count := range snap { + fmt.Println(s, count) + } +} + +func getMax(m map[uint64]int) int { + var max int + for _, v := range m { + if v > max { + max = v + } + } + return max +} + +func getMin(m map[uint64]int) int { + min := math.MaxInt32 + for _, v := range m { + if v < min { + min = v + } + } + return min +} + +func getSum(m map[uint64]int) int { + var sum int + for _, v := range m { + sum += v + } + return sum +} diff --git a/pkg/faketikv/task.go b/pkg/faketikv/task.go index 20bbe992583..2fc225343b2 100644 --- a/pkg/faketikv/task.go +++ b/pkg/faketikv/task.go @@ -141,6 +141,7 @@ func (m *mergeRegion) Step(r *RaftEngine) { r.SetRegion(targetRegion) r.recordRegionChange(targetRegion) + r.schedulerStats.taskStats.mergeRegion++ m.finished = true } @@ -179,6 +180,16 @@ func (t *transferLeader) Step(r *RaftEngine) { t.finished = true r.SetRegion(region) r.recordRegionChange(region) + fromPeerID := t.fromPeer.GetId() + toPeerID := t.peer.GetId() + _, ok := r.schedulerStats.taskStats.transferLeader[fromPeerID] + if ok { + r.schedulerStats.taskStats.transferLeader[fromPeerID][toPeerID]++ + } else { + m := make(map[uint64]int) + m[toPeerID]++ + r.schedulerStats.taskStats.transferLeader[fromPeerID] = m + } } func (t *transferLeader) RegionID() uint64 { @@ -225,6 +236,7 @@ func (a *addPeer) Step(r *RaftEngine) { if !processSnapshot(sendNode, a.sendingStat, snapshotSize) { return } + r.schedulerStats.snapshotStats.send[sendNode.Id]++ recvNode := r.conn.Nodes[a.peer.GetStoreId()] if recvNode == nil { @@ -235,13 +247,16 @@ func (a *addPeer) Step(r *RaftEngine) { if !processSnapshot(recvNode, a.receivingStat, snapshotSize) { return } + r.schedulerStats.snapshotStats.receive[recvNode.Id]++ a.size -= a.speed if a.size < 0 { if region.GetPeer(a.peer.GetId()) == nil { region.AddPeer(a.peer) + r.schedulerStats.taskStats.addPeer[region.GetId()]++ } else { region.GetPeer(a.peer.GetId()).IsLearner = false + r.schedulerStats.taskStats.promoteLeaner[region.GetId()]++ } region.RegionEpoch.ConfVer++ r.SetRegion(region) @@ -300,6 +315,7 @@ func (a *removePeer) Step(r *RaftEngine) { } r.SetRegion(region) r.recordRegionChange(region) + r.schedulerStats.taskStats.removePeer[region.GetId()]++ if r.conn.Nodes[storeID] == nil { a.finished = true return @@ -351,6 +367,7 @@ func (a *addLearner) Step(r *RaftEngine) { region.RegionEpoch.ConfVer++ r.SetRegion(region) r.recordRegionChange(region) + r.schedulerStats.taskStats.addLearner[region.GetId()]++ } a.finished = true } From cdfcec35f1021e7fab2742df0476fb778c6c14bb Mon Sep 17 00:00:00 2001 From: rleungx Date: Wed, 29 Aug 2018 20:04:10 +0800 Subject: [PATCH 2/2] address comment --- cmd/simulator/main.go | 2 +- pkg/faketikv/drive.go | 6 +++--- pkg/faketikv/statistics.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/simulator/main.go b/cmd/simulator/main.go index c3639d0705d..d2806d39676 100644 --- a/cmd/simulator/main.go +++ b/cmd/simulator/main.go @@ -174,7 +174,7 @@ EXIT: } fmt.Printf("%s [%s] total iteration: %d, time cost: %v\n", simResult, confName, driver.TickCount(), time.Since(start)) - driver.Print() + driver.PrintStatistics() if simResult != "OK" { os.Exit(1) diff --git a/pkg/faketikv/drive.go b/pkg/faketikv/drive.go index f6453fb4980..b1bc95541a0 100644 --- a/pkg/faketikv/drive.go +++ b/pkg/faketikv/drive.go @@ -124,9 +124,9 @@ func (d *Driver) Check() bool { return d.conf.Checker(d.raftEngine.regionsInfo) } -// Print prints the statistics of the scheduler. -func (d *Driver) Print() { - d.raftEngine.schedulerStats.Print() +// PrintStatistics prints the statistics of the scheduler. +func (d *Driver) PrintStatistics() { + d.raftEngine.schedulerStats.PrintStatistics() } // Stop stops all nodes. diff --git a/pkg/faketikv/statistics.go b/pkg/faketikv/statistics.go index 91f9115831d..9f4e4fccd57 100644 --- a/pkg/faketikv/statistics.go +++ b/pkg/faketikv/statistics.go @@ -104,8 +104,8 @@ func (s *snapshotStatistics) getStatistics() map[string]int { return stats } -// Print prints the statistics of the scheduler. -func (s *schedulerStatistics) Print() { +// PrintStatistics prints the statistics of the scheduler. +func (s *schedulerStatistics) PrintStatistics() { task := s.taskStats.getStatistics() snap := s.snapshotStats.getStatistics() for t, count := range task {