Update dependencies
This commit is contained in:
113
vendor/gvisor.dev/gvisor/pkg/buffer/chunk.go
vendored
Normal file
113
vendor/gvisor.dev/gvisor/pkg/buffer/chunk.go
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/bits"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// This is log2(baseChunkSize). This number is used to calculate which pool
|
||||
// to use for a payload size by right shifting the payload size by this
|
||||
// number and passing the result to MostSignificantOne64.
|
||||
baseChunkSizeLog2 = 6
|
||||
|
||||
// This is the size of the buffers in the first pool. Each subsequent pool
|
||||
// creates payloads 2^(pool index) times larger than the first pool's
|
||||
// payloads.
|
||||
baseChunkSize = 1 << baseChunkSizeLog2 // 64
|
||||
|
||||
// MaxChunkSize is largest payload size that we pool. Payloads larger than
|
||||
// this will be allocated from the heap and garbage collected as normal.
|
||||
MaxChunkSize = baseChunkSize << (numPools - 1) // 64k
|
||||
|
||||
// The number of chunk pools we have for use.
|
||||
numPools = 11
|
||||
)
|
||||
|
||||
// chunkPools is a collection of pools for payloads of different sizes. The
|
||||
// size of the payloads doubles in each successive pool.
|
||||
var chunkPools [numPools]sync.Pool
|
||||
|
||||
func init() {
|
||||
for i := 0; i < numPools; i++ {
|
||||
chunkSize := baseChunkSize * (1 << i)
|
||||
chunkPools[i].New = func() any {
|
||||
return &chunk{
|
||||
data: make([]byte, chunkSize),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition: 0 <= size <= maxChunkSize
|
||||
func getChunkPool(size int) *sync.Pool {
|
||||
idx := 0
|
||||
if size > baseChunkSize {
|
||||
idx = bits.MostSignificantOne64(uint64(size) >> baseChunkSizeLog2)
|
||||
if size > 1<<(idx+baseChunkSizeLog2) {
|
||||
idx++
|
||||
}
|
||||
}
|
||||
if idx >= numPools {
|
||||
panic(fmt.Sprintf("pool for chunk size %d does not exist", size))
|
||||
}
|
||||
return &chunkPools[idx]
|
||||
}
|
||||
|
||||
// Chunk represents a slice of pooled memory.
|
||||
//
|
||||
// +stateify savable
|
||||
type chunk struct {
|
||||
chunkRefs
|
||||
data []byte
|
||||
}
|
||||
|
||||
func newChunk(size int) *chunk {
|
||||
var c *chunk
|
||||
if size > MaxChunkSize {
|
||||
c = &chunk{
|
||||
data: make([]byte, size),
|
||||
}
|
||||
} else {
|
||||
pool := getChunkPool(size)
|
||||
c = pool.Get().(*chunk)
|
||||
clear(c.data)
|
||||
}
|
||||
c.InitRefs()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *chunk) destroy() {
|
||||
if len(c.data) > MaxChunkSize {
|
||||
c.data = nil
|
||||
return
|
||||
}
|
||||
pool := getChunkPool(len(c.data))
|
||||
pool.Put(c)
|
||||
}
|
||||
|
||||
func (c *chunk) DecRef() {
|
||||
c.chunkRefs.DecRef(c.destroy)
|
||||
}
|
||||
|
||||
func (c *chunk) Clone() *chunk {
|
||||
cpy := newChunk(len(c.data))
|
||||
copy(cpy.data, c.data)
|
||||
return cpy
|
||||
}
|
||||
Reference in New Issue
Block a user