改进空闲时间算法

This commit is contained in:
GoEdgeLab
2024-04-18 10:02:09 +08:00
parent 64dd4feb44
commit 8075e19d5b
2 changed files with 69 additions and 28 deletions

View File

@@ -9,6 +9,7 @@ import (
fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs" fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/shirou/gopsutil/v3/load" "github.com/shirou/gopsutil/v3/load"
"math"
"os" "os"
"sort" "sort"
"time" "time"
@@ -18,7 +19,7 @@ const maxSamples = 7
const cacheFile = "idles.cache" const cacheFile = "idles.cache"
var hourlyLoadMap = map[int]*HourlyLoad{} var hourlyLoadMap = map[int]*HourlyLoad{}
var minLoadHour = -1 var sharedMinLoadHours []int
type HourlyLoad struct { type HourlyLoad struct {
Hour int `json:"hour"` Hour int `json:"hour"`
@@ -35,7 +36,10 @@ func init() {
{ {
data, err := os.ReadFile(Tea.Root + "/data/" + cacheFile) data, err := os.ReadFile(Tea.Root + "/data/" + cacheFile)
if err == nil { if err == nil {
_ = json.Unmarshal(data, &hourlyLoadMap) err = json.Unmarshal(data, &hourlyLoadMap)
if err == nil {
calculateMinLoadHours()
}
} }
} }
@@ -70,36 +74,37 @@ func CheckHourlyLoad(hour int) {
for _, v := range hourlyLoad.Values { for _, v := range hourlyLoad.Values {
sum += v sum += v
} }
hourlyLoad.Avg = sum / float64(len(hourlyLoad.Values)) hourlyLoad.Avg = math.Ceil(sum/float64(len(hourlyLoad.Values))*10) / 10 // fix precision
// calculate min load hour calculateMinLoadHours()
var allLoads = []*HourlyLoad{}
for _, v := range hourlyLoadMap {
allLoads = append(allLoads, v)
}
sort.Slice(allLoads, func(i, j int) bool {
return allLoads[i].Avg < allLoads[j].Avg
})
minLoadHour = allLoads[0].Hour
// write to cache
hourlyLoadMapJSON, err := json.Marshal(hourlyLoadMap)
if err == nil {
_ = os.WriteFile(Tea.Root+"/data/"+cacheFile, hourlyLoadMapJSON, 0666)
}
} }
func Run(f func()) { func Run(f func()) {
defer f() defer f()
if minLoadHour < 0 { var minLoadHours = sharedMinLoadHours // copy
if len(minLoadHours) == 0 {
fsutils.WaitLoad(15, 8, time.Hour) fsutils.WaitLoad(15, 8, time.Hour)
return return
} }
var hour = time.Now().Hour() var hour = time.Now().Hour()
var minLoadHour = -1
for _, v := range minLoadHours {
if v == hour {
minLoadHour = v
break
}
if v > hour {
minLoadHour = v
break
}
}
if minLoadHour < 0 {
minLoadHour = minLoadHours[0]
}
if minLoadHour == hour { if minLoadHour == hour {
fsutils.WaitLoad(15, 10, time.Minute) fsutils.WaitLoad(15, 10, time.Minute)
return return
@@ -119,8 +124,39 @@ func RunTicker(ticker *time.Ticker, f func()) {
} }
} }
func TestMinLoadHour() int { func calculateMinLoadHours() {
return minLoadHour var allLoads = []*HourlyLoad{}
for _, v := range hourlyLoadMap {
allLoads = append(allLoads, v)
}
sort.Slice(allLoads, func(i, j int) bool {
return allLoads[i].Avg < allLoads[j].Avg
})
var minAvgLoad = allLoads[0].Avg
var newMinLoadHours []int
for _, v := range allLoads {
if v.Avg == minAvgLoad {
newMinLoadHours = append(newMinLoadHours, v.Hour)
}
}
sort.Ints(newMinLoadHours)
sharedMinLoadHours = newMinLoadHours
// write to cache
hourlyLoadMapJSON, err := json.Marshal(hourlyLoadMap)
if err == nil {
_ = os.WriteFile(Tea.Root+"/data/"+cacheFile, hourlyLoadMapJSON, 0666)
}
}
func TestMinLoadHours() []int {
return sharedMinLoadHours
}
func TestSetMinLoadHours(minLoadHours []int) {
sharedMinLoadHours = minLoadHours
} }
func TestHourlyLoadMap() map[int]*HourlyLoad { func TestHourlyLoadMap() map[int]*HourlyLoad {

View File

@@ -5,7 +5,8 @@ package idles_test
import ( import (
"github.com/TeaOSLab/EdgeNode/internal/utils/idles" "github.com/TeaOSLab/EdgeNode/internal/utils/idles"
"github.com/TeaOSLab/EdgeNode/internal/utils/testutils" "github.com/TeaOSLab/EdgeNode/internal/utils/testutils"
"github.com/iwind/TeaGo/logs" _ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time" timeutil "github.com/iwind/TeaGo/utils/time"
"testing" "testing"
"time" "time"
@@ -13,17 +14,21 @@ import (
func TestCheckHourlyLoad(t *testing.T) { func TestCheckHourlyLoad(t *testing.T) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
idles.CheckHourlyLoad(5)
idles.CheckHourlyLoad(1) idles.CheckHourlyLoad(1)
idles.CheckHourlyLoad(2)
idles.CheckHourlyLoad(3) idles.CheckHourlyLoad(3)
idles.CheckHourlyLoad(2)
idles.CheckHourlyLoad(4)
} }
t.Log(idles.TestMinLoadHour()) t.Log(idles.TestMinLoadHours())
logs.PrintAsJSON(idles.TestHourlyLoadMap(), t) for h, v := range idles.TestHourlyLoadMap() {
t.Log(types.String(h)+":", v.Avg)
}
} }
func TestRun(t *testing.T) { func TestRun(t *testing.T) {
//idles.CheckHourlyLoad(time.Now().Hour()) idles.TestSetMinLoadHours([]int{0, time.Now().Hour()})
idles.Run(func() { idles.Run(func() {
t.Log("run once") t.Log("run once")
}) })