
Вступление
Всем привет! Я начинающий разработчик на языке Go. До этого у меня был, так сказать, небольшой опыт, но в виде хобби. Во время изучения я также осваивал Linux, сейчас уже пользуюсь им как основной ОС.
Мой ноутбук довольно слабый, на борту всего 4ГБ ОЗУ, а на Windows существует программа, которая автоматически очищала оперативную память. Поискав в интернете, я понял, что нету такой утилиты, которая быстро и легко могла очистить оперативную память от мусора. Тогда я принялся попробовать написать ее самостоятельно.
В этой статье я расскажу, что я узнал об оперативной памяти и какими способами ее можно очистить.
Немного о кеше оперативной памяти и пример на Go
Немного порыскав в интернете, я нашел информацию о кеше, который копится в оперативной памяти. Всего их два вида:
-
PageCache — это то место, куда ядро складывает данные, которые мы записывали/читали из диска.
-
inode/dentrie — сюда записывается структура файловой системы, расположение файлов и папок.
Для их очистки достаточно ввести одну команду (от суперпользователя):
sync; echo 3 > /proc/sys/vm/drop_caches
Рассмотрим, что же это значит:
-
sync— синхронизирует данные на диске с данными в оперативной памяти -
Запись числа 3 в
/proc/sys/vm/drop_caches— сигнал для ядра ОС, что необходимо очистить PageCache, inode и dentrie
Вот как выполнение данной команды может выглядеть в Go:
import ( "os" "os/exec" ) func cleanRamCache() error { err := exec.Command("sync").Run() if err != nil { return err } err = os.WriteFile("/proc/sys/vm/drop_caches", []byte("3"), 0) if err != nil { return err } return nil }
В данной функции мы выполнили команду sync, а также дали ядру Linux сигнал о том, что нужно освободить кэш, записав число 3 в файл /proc/sys/vm/drop_caches.
Перезагрузка Swap файла
Далее, мы можем повысить производительность, переместив данные из Swap в оперативную память. Для этого используется данная команда (также от суперпользователя):
swapoff -a && swapon -a # Выключение и последующее включение Swap
Вызов данной команды в Go:
import "os/exec" func restartSwap() error { cmd := "swapoff -a && swapon -a" err := exec.Command("bash", "-c", cmd).Run() if err != nil { return err } return nil }
Но стоит учесть, что данное действие повысит расход оперативной памяти, так как все данные из Swap перемещаются в неё.
Получение информации об оперативной памяти
Также хотелось реализовать в утилите информацию об оперативной памяти. Для этого я использовал cgo (Вызов функций C из Go):
// #include <unistd.h> import "C" import "fmt" func getRam() (string, string) { bTotal := C.sysconf(C._SC_PHYS_PAGES) * C.sysconf(C._SC_PAGE_SIZE) gbTotal := float64(bTotal) / 1024 / 1024 / 1024 fmtTotal := fmt.Sprintf("Total: %.1f GB", gbTotal) bFree := C.sysconf(C._SC_AVPHYS_PAGES) * C.sysconf(C._SC_PAGE_SIZE) gbFree := float64(bFree) / 1024 / 1024 / 1024 fmtFree := fmt.Sprintf("Free: %.1f GB", gbFree) return fmtTotal, fmtFree }
Рассмотрим, что выполняет данная функция:
-
Получает информацию об объеме оперативной памяти в байтах, используя функцию
sysconfс аргументом_SC_PHYS_PAGES(количество страниц физической памяти), переводит в гигабайты и записывает форматированную информацию вfmtTotal -
Делает тоже самое для получения доступной оперативной памяти (
_SC_AVPHYS_PAGES) -
Возвращает две строковые переменные с информацией об обьеме оперативной памяти и доступной памяти на данный момент
А зачем вообще это нужно?
Данная утилита была бы полезна людям, которые еще не освоились в Linux, и привыкли к таким программам, как Mem Reduct в Windows. Да, это только маленькая часть того, что можно реализовать в данной программе. Но я уже немного расширил функционал программы, добавив флаги, дополнительные проверки и даже локализацию. Полный код утилиты можно посмотреть моем репозитории. Буду только рад вашим идеям по расширению функционала утилиты. Если вам понравилась эта статья, в следующей я могу описать другие части функционала программы, а также способ автоматизировать очистку. Хорошего вечера!
ссылка на оригинал статьи https://habr.com/ru/post/711186/
Добавить комментарий