Вечеринка гоферов

14 июля 2023
Вечеринка гоферов

Отвлекитесь от абстракций. Сегодня мы поговорим, как извлекать данные об оборудовании с помощью 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 проектах и выступления на конференциях, а расти в грейдах можно с помощью честной системы проверки навыков и менторства.

Подробнее

 

Подписаться
на Digest →
Важные новости и мероприятия без спама
Технологии которыми вы владеете и которые вам интересны
Ваш адрес электронной почты в безопасности - вот наша политика конфиденциальности.