Go sync.pool намного медленнее, чем make? - PullRequest
0 голосов
/ 04 декабря 2018

Я пытался использовать sync.Pool для повторного использования []byte.Но это оказалось медленнее, чем просто сделать.Код:

package main

import (
    "sync"
    "testing"
)

func BenchmarkMakeStack(b *testing.B) {
    for N := 0; N < b.N; N++ {
        obj := make([]byte, 1024)
        _ = obj
    }
}

var bytePool = sync.Pool{
    New: func() interface{} {
        b := make([]byte, 1024)
        return &b
    },
}

func BenchmarkBytePool(b *testing.B) {
    for N := 0; N < b.N; N++ {
        obj := bytePool.Get().(*[]byte)
        _ = obj
        bytePool.Put(obj)
    }
}

Результат:

$ go test pool_test.go -bench=. -benchmem
BenchmarkMakeStack-4    2000000000      0.29 ns/op       0 B/op    0 allocs/op
BenchmarkBytePool-4      100000000     17.2 ns/op        0 B/op    0 allocs/op

Согласно документам Go, sync.Pool должно быть быстрее, но мой тест показал обратное.Кто-нибудь может мне помочь объяснить это?

Обновление: 1. обновите соответствующий код, используя go benchmark.2. ответ лежит в стеке и куче , см. Ответ peterSO.

1 Ответ

0 голосов
/ 04 декабря 2018

Первый закон эталонных тестов: бессмысленные микробенчмарки дают бессмысленные результаты.

Ваши нереальные микробенчмарки не имеют смысла.


Синхронизация пакетов

import "sync"

тип Пул

Пул - это набор временных объектов, которые могут быть индивидуально сохранены и извлечены.

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

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

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

Надлежащим использованием пула является управление группой временных элементов, которые совместно используются и могут использоваться повторно независимыми клиентами пакета, которые могут использоваться повторно.Пул позволяет амортизировать накладные расходы при распределении между многими клиентами.

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

С другой стороны, свободный список, поддерживаемый как часть недолговечного объекта, не подходит для пула,поскольку накладные расходы плохо амортизируются в этом сценарии.Более эффективно, чтобы такие объекты реализовывали свой собственный свободный список.

Подходит ли sync.Pool для вашего варианта использования?sync.Pool подходит для вашего теста?Ваш сценарий использования и ваш тест совпадают?Является ли ваш вариант использования микробенчмарком?


При использовании пакета Go testing для ваших искусственных тестов с отдельными тестами для make стеков и выделений кучи, make быстрее и медленнее, чем sync.Pool.

Выход:

$ go test pool_test.go -bench=. -benchmem
BenchmarkMakeStack-4    2000000000      0.29 ns/op       0 B/op    0 allocs/op
BenchmarkMakeHeap-4       10000000    136 ns/op       1024 B/op    1 allocs/op
BenchmarkBytePool-4      100000000     17.2 ns/op        0 B/op    0 allocs/op
$

pool_test.go:

package main

import (
    "sync"
    "testing"
)

func BenchmarkMakeStack(b *testing.B) {
    for N := 0; N < b.N; N++ {
        obj := make([]byte, 1024)
        _ = obj
    }
}

var obj []byte

func BenchmarkMakeHeap(b *testing.B) {
    for N := 0; N < b.N; N++ {
        obj = make([]byte, 1024)
        _ = obj
    }
}

var bytePool = sync.Pool{
    New: func() interface{} {
        b := make([]byte, 1024)
        return &b
    },
}

func BenchmarkBytePool(b *testing.B) {
    for N := 0; N < b.N; N++ {
        obj := bytePool.Get().(*[]byte)
        _ = obj
        bytePool.Put(obj)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...