Я работаю над чат-ботом для сайта Twitch.tv, который написан на Go.
Одной из особенностей бота является система начисления очков, которая поощряет пользователей за просмотр определенного потока. Эти данные хранятся в базе данных SQLite3.
Чтобы получить зрителей, бот делает вызов API, чтобы дергаться и собирает всех текущих зрителей потока. Эти зрители затем помещают в кусочек строк.
Общее количество зрителей может варьироваться от пары до 20000 и более.
Что делает бот
- Делает вызов API
- Хранит всех зрителей в виде строки строк
- Для каждого зрителя бот повторяет и добавляет очки соответственно.
- Бот очищает этот срез перед следующей итерацией
Код
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 МБ ОЗУ до 20 МБ +. Конечно, тысячи элементов занимают много места!
Однако что-то еще происходит.
Фактическое поведение
Каждый раз, когда вызывается API, ОЗУ увеличивается, как и ожидалось. Но поскольку я очищаю фрагмент, я ожидаю, что он вернется к своему «нормальному» 3,0 МБ использования.
Однако объем использования ОЗУ увеличивается за один вызов API и не уменьшается, даже если общее число зрителей потока увеличивается.
Таким образом, , учитывая несколько часов, бот легко будет потреблять 100 + МБ ОЗУ, что мне не кажется правильным.
Что мне здесь не хватает? Я довольно новичок в программировании и CS в целом, поэтому, возможно, я пытаюсь исправить то, что не является проблемой. Но это звучит как утечка памяти для меня.
Я попытался форсировать сборку мусора и освободить память через библиотеку времени исполнения Голанга, но это не исправляет.