因此,我正在构建一个小型实用程序,该实用程序侦听套接字,并将传入消息作为结构存储在切片中:
var points []Point
type Point struct {
time time.Time
x float64
y float64
}
func main() {
received = make([]Point, 0)
l, err := net.Listen("tcp4", ":8900")
// (...)
}
func processIncomingData(data string) {
// Parse icoming data that comes as: xValue,yValue
inData = strings.Split(data, ",")
x, err := strconv.ParseFloat(inData[0], 64);
if err != nil {
fmt.Println(err)
}
y, err := strconv.ParseFloat(inData[1], 64);
if err != nil {
fmt.Println(err)
}
// Store the new Point
points = append(points, Point{
time: time.Now(),
x: x,
y: y,
})
// Remove points older than 1h ?
}
现在,您可能会想像,这将很快填满我的RAM。 在应用每个新点后,最好的方法(更快的执行)是删除早于1h的点?我将获得10-15倍同行的新分数。
谢谢。
答案 0 :(得分:2)
我已经使用过几次的方法是在项目的早期开始一个goroutine,如下所示:
go cleanup()
...
func cleanup() {
for {
time.Sleep(...)
// do cleanup
}
}
然后,您可以做的是使用points
在time.Since(point.time)
上进行迭代,以找出每条数据的年代。如果太旧,可以使用slice trick从切片中移除其位置:
points = append(points[:i], points[i+1:]...)
(其中i
是要删除的索引)
由于这些点按添加时间的顺序排列在切片中,因此您可以通过简单地找到不存在一个小时的第一个索引并执行points = points[i:]
来删除旧点来加快处理速度从切片的开头开始。
如果在清理阵列时收到访问阵列的请求,则可能会遇到问题。添加sync.Mutex
可以帮助您。只需在清理之前锁定互斥锁,然后尝试将互斥锁锁定到您写入阵列的其他任何位置。不过,这可能是过早的优化。在添加互斥锁之前,我会尝试不使用互斥锁,因为这样可以有效地与points
进行串行操作并降低服务速度。
循环中的time.Sleep(...)
是为了防止清洁太频繁。您可能会想将其设置为一个小时,因为您想删除早于该时间的点,但最终可能会导致在清理后立即添加一个点。在下一次清理中,它的存在时间为59分钟,并且您不会将其删除;在下一次清理中,它的存在时间已近2个小时。我的经验法则是,我尝试每1/10清理一次我想让一个对象保留在内存中的时间,但这相当随意。这种方法意味着删除一个对象时,该对象的最长寿命可能为1h 5m 59s。