Вечеринка гоферов
Отвлекитесь от абстракций. Сегодня мы поговорим, как извлекать данные об оборудовании с помощью ghw, делать запросы в генеративные нейросети OpenAI и даже скачивать себе на компьютер больше оперативной памяти… серьёзно!
Читаем состав
Мы привыкли, что работаем с абстракциями. Это облегчает жизнь и позволяет лишний раз не думать о совместимости. Яркий пример — облака. Приложение работает внутри виртуальной машины или контейнера, а все вопросы совместимости ложатся на провайдера инфраструктуры. В случае с виртуальными машинами приложение думает, что работает на реальном процессоре и использует дисковый накопитель, в то время как оперирует лишь эмулированными представлениями. Всю низкоуровневую работу берёт на себя инфраструктура.
Давайте отвлечёмся от привычного и посмотрим на небольшую библиотеку ghw (Golang HardWare). Её задача: определение и проверка работы оборудования. Она полностью поддерживает операционные системы Windows и Linux, а также частично macOS. Часть функций ghw работает без root-привилегий. Если какую-то часть информации считать не удалось, то библиотека не станет генерировать ошибку, а всего лишь выдаст warning message. Кстати, эти сообщения можно отключить через переменную окружения.
Скажем сразу, что ghw не годится на роль системного монитора. Если надо собирать и анализировать метрики, вам подойдёт самый обычный Prometheus. Библиотека gwh нужна, чтобы собирать подробную информацию обо всех возможностях оборудования хоста. В качестве источников данных используются штатные утилиты операционной системы. Так, например, в Linux для получения информации о CPU используется /proc/cpuinfo, а для расширенных данных о сетевых адаптерах — ethtool.
Вот пример запроса данных об установленных процессорах:
package main
import (
"fmt"
"math"
"strings"
"github.com/jaypipes/ghw"
)
func main() {
cpu, err := ghw.CPU()
if err != nil {
fmt.Printf("Error getting CPU info: %v", err)
}
fmt.Printf("%v\n", cpu)
for _, proc := range cpu.Processors {
fmt.Printf(" %v\n", proc)
for _, core := range proc.Cores {
fmt.Printf(" %v\n", core)
}
if len(proc.Capabilities) > 0 {
// pretty-print the (large) block of capability strings into rows
// of 6 capability strings
rows := int(math.Ceil(float64(len(proc.Capabilities)) / float64(6)))
for row := 1; row < rows; row = row + 1 {
rowStart := (row * 6) - 1
rowEnd := int(math.Min(float64(rowStart+6), float64(len(proc.Capabilities))))
rowElems := proc.Capabilities[rowStart:rowEnd]
capStr := strings.Join(rowElems, " ")
if row == 1 {
fmt.Printf(" capabilities: [%s\n", capStr)
} else if rowEnd < len(proc.Capabilities) {
fmt.Printf(" %s\n", capStr)
} else {
fmt.Printf(" %s]\n", capStr)
}
}
}
}
}
Пример вывода:
cpu (1 physical package, 6 cores, 12 hardware threads)
physical package #0 (6 cores, 12 hardware threads)
processor core #0 (2 threads), logical processors [0 6]
processor core #1 (2 threads), logical processors [1 7]
processor core #2 (2 threads), logical processors [2 8]
processor core #3 (2 threads), logical processors [3 9]
processor core #4 (2 threads), logical processors [4 10]
processor core #5 (2 threads), logical processors [5 11]
capabilities: [msr pae mce cx8 apic sep
mtrr pge mca cmov pat pse36
clflush dts acpi mmx fxsr sse
sse2 ss ht tm pbe syscall
nx pdpe1gb rdtscp lm constant_tsc arch_perfmon
pebs bts rep_good nopl xtopology nonstop_tsc
cpuid aperfmperf pni pclmulqdq dtes64 monitor
ds_cpl vmx est tm2 ssse3 cx16
xtpr pdcm pcid sse4_1 sse4_2 popcnt
aes lahf_lm pti retpoline tpr_shadow vnmi
flexpriority ept vpid dtherm ida arat]
Получаемые данные можно сериализовать двумя способами: превратить в JSON или YAML. Для этого предусмотрены методы JSONString() и YAMLString(). Ещё одна полезная фича — возможность создания снапшотов. Работает она пока только с Linux, а снапшоты представляют собой частичные копии деревьев /proc и /sys. В снапшот включаются только те данные, которые могут быть сняты при помощи ghw.
Играем с OpenAI
Только ленивый сейчас не говорит о продуктах OpenAI. Эта компания изначально была некоммерческим проектом, а ныне объединила усилия с Microsoft и получила от них внешнее финансирование. Множество разработок OpenAI уже были представлены общественности. Среди них чат-бот ChatGPT, генеративная нейросеть DALL-E, система распознавания голоса Whisper и большие языковые модели (LLM) GPT-3 и GPT-4.
OpenAI даёт доступ к своим продуктам через собственное API и предоставляет документацию, позволяющую создавать приложения на их основе. Но вместо того, чтобы каждый раз создавать собственную «обёртку», проще воспользоваться готовой. Такой как go-openai, содержащей неофициальные клиенты OpenAI API. Устанавливается стандартно, через go get:
go get github.com/sashabaranov/go-openai
Прежде чем использовать go-openai, нужно получить ключ доступа к API. Для этого надо зайти по адресу https://platform.openai.com/account/api-keys, cоздать аккаунт и сгенерировать секретный ключ на странице управления доступом. Помните, что ключ относится к чувствительным данным и его нельзя раскрывать третьим лицам. Теперь можно выполнять запросы, например:
package main
import (
"context"
"fmt"
openai "github.com/sashabaranov/go-openai"
)
func main() {
client := openai.NewClient("your token")
resp, err := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: "Hello!",
},
},
},
)
if err != nil {
fmt.Printf("ChatCompletion error: %v\n", err)
return
}
fmt.Println(resp.Choices[0].Message.Content)
}
Жонглируем оперативной памятью
Помните знаменитое высказывание Билла Гейтса про то, что 640 КБ ОЗУ хватит всем? Шутить над ним, на самом деле, начали ещё до капитальных изменений порядка доступа к памяти в Windows NT. Чтобы запускать сложные приложения или игры, приходилось задействовать расширители памяти, вроде CWSDPMI. Это позволяло обходить существующие ограничения и использовать всю доступную оперативную память.
Когда приложение не помещается в RAM, задействуется swap. Традиционно это файл или отдельный раздел на локальном дисковом накопителе. Без этого приложение прекратило бы работу, выдав ошибку. Размер swap-раздела может быть любым, но на практике он ограничивается объёмом локального диска. Недостатком swap на диске можно считать большое значение latency, в тысячи раз медленнее, чем с обычной ОЗУ. Концепция «всё есть файл» в Linux позволяет обойти и это ограничение, выполняя хранение данных swap не на локальном накопителе, а примонтировав часть оперативной памяти с другой машины.
В основе проекта ram-dl лежит go-nbd, серверная часть и клиентская библиотека для управления сетевыми блочными устройствами. Объединив это с r3map, библиотекой монтирования и миграции оперативной памяти, получаем уникальный инструмент, позволяющий расширить swap до любого размера. Это может пригодиться в разных сценариях: от тестирования до запуска специализированных приложений.
Выглядит монтирование RAM следующим образом: на удалённой системе запускается серверная часть, которая резервирует участок памяти и делает его доступным по fRPC. Клиентская часть изменяет поведение команд mkswap, swapon и swapoff, заворачивая их на fRPC-бекэнд. На скоростных линиях связи производительность такого трюка будет сравнима с производительностью локального накопителя.
Интересно посмотреть
Пропустили наш предыдущий митап? Не страшно! Видеозаписи докладов уже выложены на нашем YouTube-канале в кинематографическом качестве 4K и со студийным звуком.
Подписывайтесь и ставьте 🔔колокольчик, чтобы получать уведомления о будущих трансляциях и видео! А ещё присоединяйтесь к Telegram-каналу и будьте в курсе всех наших будущих мероприятий.
Митапы
Go meetup
13 сентября 2023
Осенью у нас запланирован Go Meetup. Программа мероприятия формируется, но регистрация уже открыта. Кстати, вы уже можете подать доклад прямо в режиме онлайн. Заявки на участие спикера принимаются до 20 августа.
Интересуетесь нашими мероприятиями? В Telegram-канале Evrone meetups мы выкладываем анонсы с подробными описаниями докладов, а также студийные записи прошедших митапов. Тем для кого выступать в новинку, мы оказываем всяческую поддержку и помогаем оформить экспертизу в яркое выступление. Подписывайтесь и пишите @andrew_aquariuss, чтобы узнать подробности.
Вакансии
Удаленка / Офис
Evrone
Мы открыты для новых Go-разработчиков. В Evrone можно работать удалённо с первого дня, мы поддерживаем и оплачиваем участие в Open-source проектах и выступления на конференциях, а расти в грейдах можно с помощью честной системы проверки навыков и менторства.