diff --git a/server/cluster/cluster.go b/server/cluster/cluster.go index 794dc351813..516ffa2eb08 100644 --- a/server/cluster/cluster.go +++ b/server/cluster/cluster.go @@ -615,6 +615,11 @@ func (c *RaftCluster) GetSuspectRegions() []uint64 { return c.coordinator.checkers.GetSuspectRegions() } +// GetHotStat gets hot stat for test. +func (c *RaftCluster) GetHotStat() *statistics.HotStat { + return c.hotStat +} + // RemoveSuspectRegion removes region from suspect list. func (c *RaftCluster) RemoveSuspectRegion(id uint64) { c.coordinator.checkers.RemoveSuspectRegion(id) diff --git a/server/statistics/hot_peer_cache_test.go b/server/statistics/hot_peer_cache_test.go index 4698cc4769a..347e2a423d8 100644 --- a/server/statistics/hot_peer_cache_test.go +++ b/server/statistics/hot_peer_cache_test.go @@ -22,6 +22,7 @@ import ( . "github.com/pingcap/check" "github.com/pingcap/kvproto/pkg/metapb" + "github.com/tikv/pd/pkg/movingaverage" "github.com/tikv/pd/server/core" ) @@ -603,3 +604,52 @@ func BenchmarkCheckRegionFlow(b *testing.B) { } } } + +type testMovingAverageCase struct { + report []float64 + expect []float64 +} + +func checkMovingAverage(c *C, testCase *testMovingAverageCase) { + interval := 1 * time.Second + tm := movingaverage.NewTimeMedian(DefaultAotSize, DefaultWriteMfSize, interval) + var results []float64 + for _, data := range testCase.report { + tm.Add(data, interval) + results = append(results, tm.Get()) + } + c.Assert(results, DeepEquals, testCase.expect) +} + +// +func (t *testHotPeerCache) TestUnstableData(c *C) { + cases := []*testMovingAverageCase{ + { + report: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + expect: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + { + report: []float64{0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + expect: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + report: []float64{0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + expect: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + report: []float64{0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + expect: []float64{0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + }, + { + report: []float64{0, 0, 0, 0, 0, 1, 0, 1, 0, 0}, + expect: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + report: []float64{0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, + expect: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, + } + for i := range cases { + checkMovingAverage(c, cases[i]) + } +} diff --git a/server/statistics/util.go b/server/statistics/util.go index 05e7db9e0a8..8c3a89d9c8e 100644 --- a/server/statistics/util.go +++ b/server/statistics/util.go @@ -24,7 +24,7 @@ const ( // RegionHeartBeatReportInterval is the heartbeat report interval of a region. RegionHeartBeatReportInterval = 60 // DefaultAotSize is default size of average over time. - DefaultAotSize = 2 + DefaultAotSize = 1 // DefaultWriteMfSize is default size of write median filter. DefaultWriteMfSize = 5 // DefaultReadMfSize is default size of read median filter. diff --git a/tests/pdctl/hot/hot_test.go b/tests/pdctl/hot/hot_test.go index dc11efced6b..de40564c2d9 100644 --- a/tests/pdctl/hot/hot_test.go +++ b/tests/pdctl/hot/hot_test.go @@ -119,7 +119,7 @@ func (s *hotTestSuite) TestHot(c *C) { _, err = pdctl.ExecuteCommand(cmd, args...) c.Assert(err, IsNil) - hotStoreID := uint64(1) + hotStoreID := store1.Id count := 0 testHot := func(hotRegionID, hotStoreID uint64, hotType string) { args = []string{"-u", pdAddr, "hot", hotType} @@ -141,16 +141,32 @@ func (s *hotTestSuite) TestHot(c *C) { regionIDCounter++ switch hotType { case "read": - pdctl.MustPutRegion(c, cluster, hotRegionID, hotStoreID, []byte("b"), []byte("c"), core.SetReadBytes(1000000000), core.SetReportInterval(reportInterval)) + loads := []float64{ + statistics.RegionReadBytes: float64(1000000000 * reportInterval), + statistics.RegionReadKeys: float64(1000000000 * reportInterval), + statistics.RegionReadQuery: float64(1000000000 * reportInterval), + statistics.RegionWriteBytes: 0, + statistics.RegionWriteKeys: 0, + statistics.RegionWriteQuery: 0, + } + leader := &metapb.Peer{ + Id: 100 + regionIDCounter, + StoreId: hotStoreID, + } + peerInfo := core.NewPeerInfo(leader, loads, reportInterval) + region := core.NewRegionInfo(&metapb.Region{ + Id: hotRegionID, + }, leader) + rc.GetHotStat().CheckReadAsync(statistics.NewCheckPeerTask(peerInfo, region)) time.Sleep(5000 * time.Millisecond) - if reportInterval >= statistics.RegionHeartBeatReportInterval { + if reportInterval >= statistics.ReadReportInterval { count++ } testHot(hotRegionID, hotStoreID, "read") case "write": - pdctl.MustPutRegion(c, cluster, hotRegionID, hotStoreID, []byte("c"), []byte("d"), core.SetWrittenBytes(1000000000), core.SetReportInterval(reportInterval)) + pdctl.MustPutRegion(c, cluster, hotRegionID, hotStoreID, []byte("c"), []byte("d"), core.SetWrittenBytes(1000000000*reportInterval), core.SetReportInterval(reportInterval)) time.Sleep(5000 * time.Millisecond) - if reportInterval >= statistics.RegionHeartBeatReportInterval { + if reportInterval >= statistics.WriteReportInterval { count++ } testHot(hotRegionID, hotStoreID, "write")