github.com/iDigitalFlame/xmt@v0.5.4/com/limits/sweep.go (about)

     1  //go:build !nosweep
     2  // +build !nosweep
     3  
     4  // Copyright (C) 2020 - 2023 iDigitalFlame
     5  //
     6  // This program is free software: you can redistribute it and/or modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // any later version.
    10  //
    11  // This program is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    18  //
    19  
    20  package limits
    21  
    22  import (
    23  	"context"
    24  	"runtime"
    25  	"runtime/debug"
    26  	"sync/atomic"
    27  	"time"
    28  
    29  	"github.com/iDigitalFlame/xmt/device"
    30  	"github.com/iDigitalFlame/xmt/util/bugtrack"
    31  )
    32  
    33  var enabled uint32
    34  
    35  // MemorySweep enables the GC memory sweeper, which keeps the process memory
    36  // clean to prevent any crashes while in DLL format or injected. This function
    37  // only needs to be called once and will return immediately.
    38  //
    39  // The context is recommended to prevent any leaking Goroutines from being left
    40  // behind.
    41  //
    42  // Defaults to a time of one minute.
    43  func MemorySweep(x context.Context) {
    44  	MemorySweepEx(x, time.Minute)
    45  }
    46  func sweep(x context.Context, t time.Duration) {
    47  	v := time.NewTicker(t)
    48  loop:
    49  	for {
    50  		select {
    51  		case <-v.C:
    52  		case <-x.Done():
    53  			break loop
    54  		}
    55  		if bugtrack.Enabled {
    56  			bugtrack.Track("limits.sweep(): Starting GC and Free.")
    57  		}
    58  		runtime.GC()
    59  		device.FreeOSMemory()
    60  	}
    61  	if v.Stop(); bugtrack.Enabled {
    62  		bugtrack.Track("limits.sweep(): Stopping GC and Free thread.")
    63  	}
    64  }
    65  
    66  // MemorySweepEx enables the GC memory sweeper, which keeps the process memory
    67  // clean to prevent any crashes while in DLL format or injected. This function
    68  // only needs to be called once and will return immediately.
    69  //
    70  // The context is recommended to prevent any leaking Goroutines from being left
    71  // behind.
    72  //
    73  // Allows for specification of the time span between sweeps.
    74  func MemorySweepEx(x context.Context, d time.Duration) {
    75  	if d <= 0 || atomic.LoadUint32(&enabled) == 1 {
    76  		return
    77  	}
    78  	debug.SetGCPercent(60)
    79  	debug.SetTraceback("none")
    80  	runtime.SetCPUProfileRate(0)
    81  	runtime.SetBlockProfileRate(0)
    82  	runtime.SetMutexProfileFraction(0)
    83  	// NOTE(dij): Let's ignore this one for now.
    84  	//            We'll set it in our own env.
    85  	// runtime.GOMAXPROCS(runtime.NumCPU())
    86  	atomic.StoreUint32(&enabled, 1)
    87  	go sweep(x, d)
    88  }