Golang:从切片中删除早于1h的结构

时间:2019-04-29 21:49:42

标签: go

因此,我正在构建一个小型实用程序,该实用程序侦听套接字,并将传入消息作为结构存储在切片中:

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倍同行的新分数。

谢谢。

1 个答案:

答案 0 :(得分:2)

我已经使用过几次的方法是在项目的早期开始一个goroutine,如下所示:

go cleanup()

...

func cleanup() {
  for {
    time.Sleep(...)
    // do cleanup
  }
}

然后,您可以做的是使用pointstime.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。