Go: пулы

Пул — это множество некоторых объектов, которые можно извлечь из пула или вернуть обратно. Любой элемент в пуле может быть удален автоматически в любое время без уведомления. Если пул содержит единственную ссылку на объект в момент удаления, элемент будет удален из памяти.

Пулы разработаны таким образом, чтобы они были безопасны для одновременного использования несколькими горутинами.

Основная цель создания пула — это кэширование выделенных, но неиспользуемых элементов для последующего повторного использования, чтобы снизить нагрузку по выделению памяти и оптимизировать работу сборщика мусора. Что весьма актуально в высоконагруженных приложениях.

Хорошим примером правильного использования пулов является пакет fmt, который при помощи пула поддерживает динамическое хранилище временных буферов вывода.

При работе с пулами важно помнить, что пул нельзя копировать после первого использования.

Ниже приведен пример использования пула объектов:

package main

import (
  "bytes"
  "io"
  "os"
  "sync"
  "time"
)

var bufPool = sync.Pool{
  New: func() interface{} {
    return new(bytes.Buffer)
  },
}

func timeNow() time.Time {
  return time.Unix(1136214245, 0)
}

func Log(w io.Writer, key, val string) {
  b := bufPool.Get().(*bytes.Buffer)
  b.Reset()
  b.WriteString(timeNow().UTC().Format(time.RFC3339))
  b.WriteByte(' ')
  b.WriteString(key)
  b.WriteByte('=')
  b.WriteString(val)
  w.Write(b.Bytes())
  bufPool.Put(b)
}

func main() {
  Log(os.Stdout, "path", "/search?q=flowers")
}

Как мы видим из примера пул легко создать следующим кодом:


var bufPool = sync.Pool{
  New: func() interface{} {
    return new(bytes.Buffer)
  },
}

Для получения объекта из пула используем Get, который возвращает интерфейс, если в пуле есть объекты. Также метод Get может вернуть интерфейс на новый объект, если пул пуст и определен метод New, как в нашем примере. После того как объект стал нам больше не нужен, мы возвращаем его в пул при помощи метода Put.

 

02.02.2019









 
архив

подписка