mempro

package module
v0.0.0-...-b41ecff Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 9, 2023 License: Unlicense Imports: 2 Imported by: 0

README

gomempro

Расширение пакета github.com/bradfitz/gomemcache/memcache, позволяет помещать в мемкеш структуры

Предыстория

Работая с языком Perl, я привык, что там можно помещать в мемкеш структуру любой сложности (массив, хеш с многими подуровнями и т.д.). И затем получить её обратно в том же виде, даже не задумываясь о скрытых под капотом механизмах. Ну а если копнуть глубже, можно и чуть поковырять этот механизм: выбрать или написать свой сериализатор, позволяющий, к примеру, дополнительно сжимать данные.

Поэтому, я был удивлён, что аналогичный пакет для go позволяет помещать в мемкеш только строки (вернее, массивы байтов). И я написал небольшое расширение, дополняющее пакет memcached методами для работы с объектами (структурами произвольного типа).

Не смотря на простоту, тут используются многие фишки go: и встраивание структуры, и горутины с каналами, и работа с пустым интерфейсом.

Пример использования

// подключаемся к мемкешу. синтаксис полностью аналогичен пакету memcache
mc := mempro.New("127.0.0.1:11211")

// тестовая структура
type Ex struct {
    Num int
    Str string
}
x := Ex{Num: 123, Str: "abc"}

// помещаем в мемкеш
err := mc.SetStruct("key_one", x)

// то же самое, только задаём ещё время жизни - 5 минут
err := mc.SetStruct("key_one", x, 5*60)

// вытаскиваем из мемкеша
var y Ex
err = mc.GetStruct("key_one", &y)
fmt.Println(y) // {123 abc}

// мультигет
var z Ex
var w SomeOtherType // структуры могут быть разные в одном мультигете

// понадобится карта, ключами которой будут имена ключей мемкеша
// а значениями - пустые структуры, которые будут заполнены данными
list := make(map[string]any)
list["key_one"] = &z
list["key_two"] = &w 

// передаём карту в метод GetMultiStruct, который заполнит поля структур данными
err = mc.GetMultiStruct(list)
fmt.Println(list["key_one"]) // &{123 abc}
// если хотим получить не ссылку на структуру, а её саму, тогда так:
v, ok := list["key_one"].(*Ex)
fmt.Println(*v) // {123 abc}

// также можно пользоваться всеми методами memcache:
new_val, err := mc.Increment("key_three", 1)

Бенчмарки

Находятся вместе с тестами в mempro_test.go.

Сравнивал три метода. Первый - BenchmarkGetMulti, который с помощью GetMultiStruct получает за раз 100 ключей из мемкеша. Второй, BenchmarkGetSingle - те же 100 ключей, но в цикле через единичный гет. Третий, самый интересный: версия GetMultiStruct в которой дешифровка данных в структуры идёт не параллельно в горутинах, а в один поток (BenchmarkGetMultiSimple). Это позволяет сильно упростить код. Результаты:

goos: linux
goarch: amd64
pkg: github.com/vklimenkov/gomempro
cpu: 11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz
BenchmarkGetMulti-8                 4173        270738 ns/op       69922 B/op       1620 allocs/op
BenchmarkGetSingle-8                 919       1353884 ns/op       53439 B/op       1797 allocs/op
BenchmarkGetMultiSimple-8           4104        247973 ns/op       63158 B/op       1516 allocs/op

Ожидаемый результат - единичный get сильно проигрывает мульти-версии, и по скорости и по работе с памятью. А вот распараллеливание дешифровки практически ничего не даёт. Видимо, потенциальный выигрыш нивелируется усложнением кода и вводом дполнительных действий. Так что можно обойтись простой версией метода, BenchmarkGetMultiSimple

Лицензия

Свободное распространение

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MemPro

type MemPro struct {
	memcache.Client
}

наследник memcached только встроили родительскую структуру, новых полей нет

func New

func New(server ...string) *MemPro

конструктор, возвращает клиент мемкеша

func (*MemPro) GetMultiStruct

func (m *MemPro) GetMultiStruct(list map[string]any) error

достаёт из мемкеша сразу несколько ключей за один запрос это оптимальнее, чем получать их по одному через одиночные Get-ы для ускорения, декодирование происходит в несколько потоков хотя бенчмарки показывают, что ускорение по сравнению с однопоточным вариантом отсутствует

func (*MemPro) GetStruct

func (m *MemPro) GetStruct(key string, obj any) error

получает из мемкеша структуру

func (*MemPro) SetStruct

func (m *MemPro) SetStruct(key string, obj any, expiration ...int32) error

помещает в мемкеш структуру предварительно её кодирует с помощью json.Marshal третий необязательный параметр - TTL ключа в мемкеше

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL