【发布时间】:2018-09-07 20:07:51
【问题描述】:
我正在为 Twitch.tv 网站开发一个用 Go 编写的聊天机器人。
机器人的一个功能是奖励用户观看特定流的积分系统。此数据存储在 SQLite3 数据库中。
为了获得观众,机器人会调用 API 来 twitch 并收集流的所有当前观众。然后将这些查看器放入一段字符串中。
观看者总数可以从几个到 20,000 或更多不等。
机器人的作用
- 进行 API 调用
- 将所有查看器存储在一个字符串切片中
- 对于每个查看器,机器人会相应地迭代并添加点。
- Bot 在下一次迭代之前清除此切片
代码
type Viewers struct {
Chatters struct {
CurrentModerators []string `json:"moderators"`
CurrentViewers []string `json:"viewers"`
} `json:"chatters"`
}
func RunPoints(timer time.Duration, modifier int, conn net.Conn, channel string) {
database := InitializeDB() // Loads database through SQLite3 driver
var Points int
var allUsers []string
for range time.NewTicker(timer * time.Second).C {
currentUsers := GetViewers(conn, channel)
tx, err := database.Begin()
if err != nil {
fmt.Println("Error starting points transaction: ", err)
}
allUsers = append(allUsers, currentUsers.Chatters.CurrentViewers...)
allUsers = append(allUsers, currentUsers.Chatters.CurrentModerators...)
for _, v := range allUsers {
userCheck := UserInDB(database, v)
if userCheck == false {
statement, _ := tx.Prepare("INSERT INTO points (Username, Points) VALUES (?, ?)")
statement.Exec(v, 1)
} else {
err = tx.QueryRow("Select Points FROM points WHERE Username = ?", v).Scan(&Points)
if err != nil {
} else {
Points = Points + modifier
statement, _ := tx.Prepare("UPDATE points SET Points = ? WHERE username = ?")
statement.Exec(Points, v)
}
}
}
tx.Commit()
allUsers = allUsers[:0]
currentUsers = Viewers{} // Clear Viewer object struct
}
预期行为
当吸引成千上万的观众时,我自然希望系统资源会变得相当高。这可以将使用 3.0 MB RAM 的机器人变成高达 20 MB+。数以千计的元素当然会占用大量空间!
但是,发生了其他事情。
实际行为
每次调用 API 时,RAM 都会按预期增加。但是因为我清除了切片,所以我预计它会回落到“正常”的 3.0 MB 使用量。
但是,每次 API 调用的 RAM 使用量都会增加,并且即使流的观看者总数增加也不会减少。
因此,给定几个小时,该机器人将轻松消耗 100 + MB 的内存,这对我来说似乎不合适。
我在这里缺少什么?总的来说,我对编程和 CS 还很陌生,所以也许我正在尝试解决一些不成问题的问题。但这对我来说几乎听起来像是内存泄漏。
我尝试通过 Golang 的运行时库强制垃圾回收和释放内存,但这并不能解决问题。
【问题讨论】:
-
“也许我正在尝试修复一些不成问题的东西” 是的。内存管理很复杂。例如。 Go 不会将未使用的内存直接释放到操作系统。因此,即使内存已释放,您也不会看到它已释放。如果你没有遇到 OOM,那就别想了。
标签: go memory-management memory-leaks bots slice