From 526bd12a3b77135ce5f112f3195f1e7d41d965d5 Mon Sep 17 00:00:00 2001 From: hanchao Date: Fri, 16 Jun 2023 13:10:42 +0800 Subject: [PATCH 6/7] rubik: fix that value of memory.high_async_ratio lost efficacy --- pkg/services/dynmemory/dynmemory.go | 22 +++++++- pkg/services/dynmemory/fssr.go | 78 +++++++++++++++++------------ 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/pkg/services/dynmemory/dynmemory.go b/pkg/services/dynmemory/dynmemory.go index da859dd..b73f476 100644 --- a/pkg/services/dynmemory/dynmemory.go +++ b/pkg/services/dynmemory/dynmemory.go @@ -6,6 +6,7 @@ import ( "time" "isula.org/rubik/pkg/api" + "isula.org/rubik/pkg/core/typedef" "isula.org/rubik/pkg/services/helper" "k8s.io/apimachinery/pkg/util/wait" ) @@ -15,6 +16,7 @@ type DynMemoryAdapter interface { preStart(api.Viewer) error getInterval() int dynamicAdjust() + setOfflinePod(path string) error } type dynMemoryConfig struct { Policy string `json:"policy,omitempty"` @@ -42,11 +44,11 @@ type DynMemory struct { } // PreStart is an interface for calling a collection of methods when the service is pre-started -func (dynMem *DynMemory) PreStart(api api.Viewer) error { +func (dynMem *DynMemory) PreStart(viewer api.Viewer) error { if dynMem.dynMemoryAdapter == nil { return nil } - return dynMem.dynMemoryAdapter.preStart(api) + return dynMem.dynMemoryAdapter.preStart(viewer) } // SetConfig is an interface that invoke the ConfigHandler to obtain the corresponding configuration. @@ -81,6 +83,22 @@ func (dynMem *DynMemory) IsRunner() bool { return true } +// AddPod to deal the event of adding a pod. +func (dynMem *DynMemory) AddPod(podInfo *typedef.PodInfo) error { + if podInfo.Offline() { + return dynMem.dynMemoryAdapter.setOfflinePod(podInfo.Path) + } + return nil +} + +// UpdatePod to deal the pod update event. +func (dynMem *DynMemory) UpdatePod(old, new *typedef.PodInfo) error { + if new.Offline() { + return dynMem.dynMemoryAdapter.setOfflinePod(new.Path) + } + return nil +} + // newAdapter to create adapter of dyn memory. func newAdapter(policy string) DynMemoryAdapter { switch policy { diff --git a/pkg/services/dynmemory/fssr.go b/pkg/services/dynmemory/fssr.go index 9fe4042..e23a4bc 100644 --- a/pkg/services/dynmemory/fssr.go +++ b/pkg/services/dynmemory/fssr.go @@ -9,6 +9,7 @@ import ( "isula.org/rubik/pkg/api" "isula.org/rubik/pkg/common/constant" + "isula.org/rubik/pkg/common/log" "isula.org/rubik/pkg/common/util" "isula.org/rubik/pkg/core/typedef" "isula.org/rubik/pkg/core/typedef/cgroup" @@ -30,71 +31,76 @@ type fssrDynMemAdapter struct { memTotal int64 memHigh int64 reservedMem int64 - api api.Viewer count int64 + viewer api.Viewer } -// initFssrDynMemAdapter function +// initFssrDynMemAdapter initializes a new fssrDynMemAdapter struct. func initFssrDynMemAdapter() *fssrDynMemAdapter { if total, err := getFieldMemory("MemTotal"); err == nil && total > 0 { return &fssrDynMemAdapter{ memTotal: total, memHigh: total * 8 / 10, - reservedMem: total * 8 / 10, + reservedMem: total * 1 / 10, + count: 0, } } return nil } -// preStart function -func (f *fssrDynMemAdapter) preStart(api api.Viewer) error { - f.api = api +// preStart initializes the fssrDynMemAdapter with the provided viewer and +// deals with any existing pods. +func (f *fssrDynMemAdapter) preStart(viewer api.Viewer) error { + f.viewer = viewer return f.dealExistedPods() } -// getInterval function +// getInterval returns the fssrInterval value. func (f *fssrDynMemAdapter) getInterval() int { return fssrInterval } -// dynadjust function +// dynamicAdjust adjusts the memory allocation of the fssrDynMemAdapter by +// increasing or decreasing the amount of memory reserved for offline pods +// based on the current amount of free memory available on the system. func (f *fssrDynMemAdapter) dynamicAdjust() { var freeMem int64 var err error if freeMem, err = getFieldMemory("MemFree"); err != nil { return } + + var memHigh int64 = 0 if freeMem > 2*f.reservedMem { if f.count < fssrIntervalCount { f.count++ return } - memHigh := f.memHigh + f.memTotal/100 + // no risk of overflow + memHigh = f.memHigh + f.memTotal/100 if memHigh > f.memTotal*8/10 { memHigh = f.memTotal * 8 / 10 } - if memHigh != f.memHigh { - f.memHigh = memHigh - f.adjustOfflinePodHighMemory() - } } else if freeMem < f.reservedMem { - memHigh := f.memHigh - f.memTotal/10 + memHigh = f.memHigh - f.memTotal/10 if memHigh < 0 { return } if memHigh < f.memTotal*3/10 { memHigh = f.memTotal * 3 / 10 } - if memHigh != f.memHigh { - f.memHigh = memHigh - f.adjustOfflinePodHighMemory() - } } + if memHigh != f.memHigh { + f.memHigh = memHigh + f.adjustOfflinePodHighMemory() + } + f.count = 0 } +// adjustOfflinePodHighMemory adjusts the memory.high of offline pods. func (f *fssrDynMemAdapter) adjustOfflinePodHighMemory() error { - pods := listOfflinePods(f.api) + pods := listOfflinePods(f.viewer) for _, podInfo := range pods { if err := setOfflinePodHighMemory(podInfo.Path, f.memHigh); err != nil { return err @@ -103,20 +109,18 @@ func (f *fssrDynMemAdapter) adjustOfflinePodHighMemory() error { return nil } -// dealExistedPods function +// dealExistedPods handles offline pods by setting their memory.high and memory.high_async_ratio func (f *fssrDynMemAdapter) dealExistedPods() error { - pods := listOfflinePods(f.api) + pods := listOfflinePods(f.viewer) for _, podInfo := range pods { - if err := setOfflinePodHighMemory(podInfo.Path, f.memHigh); err != nil { - return err - } - if err := setOfflinePodHighAsyncRatio(podInfo.Path, highRatio); err != nil { - return err + if err := f.setOfflinePod(podInfo.Path); err != nil { + log.Errorf("set fssr of offline pod[%v] error:%v", podInfo.UID, err) } } return nil } +// listOfflinePods returns a map of offline PodInfo objects. func listOfflinePods(viewer api.Viewer) map[string]*typedef.PodInfo { offlineValue := "true" return viewer.ListPodsWithOptions(func(pi *typedef.PodInfo) bool { @@ -124,23 +128,35 @@ func listOfflinePods(viewer api.Viewer) map[string]*typedef.PodInfo { }) } -func setOfflinePodHighMemory(podPath string, high int64) error { - if err := cgroup.WriteCgroupFile(strconv.FormatUint(uint64(high), scale), memcgRootDir, +// setOfflinePod sets the offline pod for the given path. +func (f *fssrDynMemAdapter) setOfflinePod(path string) error { + if err := setOfflinePodHighAsyncRatio(path, highRatio); err != nil { + return err + } + return setOfflinePodHighMemory(path, f.memHigh) +} + +// setOfflinePodHighMemory sets the high memory limit for the specified pod in the +// cgroup memory +func setOfflinePodHighMemory(podPath string, memHigh int64) error { + if err := cgroup.WriteCgroupFile(strconv.FormatUint(uint64(memHigh), scale), memcgRootDir, podPath, highMemFile); err != nil { return err } return nil } -func setOfflinePodHighAsyncRatio(podPath string, ratio uint64) error { - if err := cgroup.WriteCgroupFile(strconv.FormatUint(ratio, scale), memcgRootDir, +// setOfflinePodHighAsyncRatio sets the high memory async ratio for a pod in an offline state. +func setOfflinePodHighAsyncRatio(podPath string, ratio uint) error { + if err := cgroup.WriteCgroupFile(strconv.FormatUint(uint64(ratio), scale), memcgRootDir, podPath, highMemAsyncRatioFile); err != nil { return err } return nil } -// getFieldMemory function +// getFieldMemory retrieves the amount of memory used by a certain field in the +// memory information file. func getFieldMemory(field string) (int64, error) { if !util.PathExist(memInfoFile) { return 0, fmt.Errorf("%v: no such file or diretory", memInfoFile) -- 2.32.1 (Apple Git-133)