diff --git a/go.mod b/go.mod index 1eea1f42..23eb8a4a 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/allegro/bigcache/v3 -go 1.16 +go 1.17 + +require golang.org/x/sys v0.1.0 diff --git a/go.sum b/go.sum index e69de29b..b69ea857 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/queue/bytes_queue.go b/queue/bytes_queue.go index c4fe2c08..62331ac8 100644 --- a/queue/bytes_queue.go +++ b/queue/bytes_queue.go @@ -57,22 +57,6 @@ func getNeededSize(length int) int { return length + header } -// NewBytesQueue initialize new bytes queue. -// capacity is used in bytes array allocation -// When verbose flag is set then information about memory allocation are printed -func NewBytesQueue(capacity int, maxCapacity int, verbose bool) *BytesQueue { - return &BytesQueue{ - array: make([]byte, capacity), - capacity: capacity, - maxCapacity: maxCapacity, - headerBuffer: make([]byte, binary.MaxVarintLen32), - tail: leftMarginIndex, - head: leftMarginIndex, - rightMargin: leftMarginIndex, - verbose: verbose, - } -} - // Reset removes all entries from queue func (q *BytesQueue) Reset() { // Just reset indexes diff --git a/queue/bytes_queue_test.go b/queue/bytes_queue_test.go index 81dd1078..a3626b43 100644 --- a/queue/bytes_queue_test.go +++ b/queue/bytes_queue_test.go @@ -94,7 +94,7 @@ func TestResetFullQueue(t *testing.T) { // then assertEqual(t, blob('c', 8), pop(queue)) - assertEqual(t, queue.Capacity(), 10) + assertEqual(t, queue.Capacity(), unixOr_int(20, 10)) } func TestReset(t *testing.T) { @@ -416,9 +416,9 @@ func TestPushEntryAfterAllocateAdditionMemory(t *testing.T) { queue.Pop() // allocate more memory - assertEqual(t, 9, queue.Capacity()) + assertEqual(t, unixOr_int(20, 9), queue.Capacity()) queue.Push([]byte("c")) - assertEqual(t, 18, queue.Capacity()) + assertEqual(t, unixOr_int(20, 18), queue.Capacity()) // push after allocate _, err := queue.Push([]byte("d")) @@ -508,3 +508,12 @@ func objectsAreEqual(expected, actual interface{}) bool { } return bytes.Equal(exp, act) } + +func unixOr_int(unix, other int) int { + switch runtime.GOOS { + case "aix", "darwin", "dragonfly", "freebsd", "openbsd", "solaris", "zos", "linux", "netbsd": + return unix + default: + return other + } +} diff --git a/queue/new_others.go b/queue/new_others.go new file mode 100644 index 00000000..b270ebd3 --- /dev/null +++ b/queue/new_others.go @@ -0,0 +1,22 @@ +//go:build !aix && !darwin && !dragonfly && !freebsd && !openbsd && !solaris && !zos && !linux && !netbsd +// +build !aix,!darwin,!dragonfly,!freebsd,!openbsd,!solaris,!zos,!linux,!netbsd + +package queue + +import "encoding/binary" + +// NewBytesQueue initialize new bytes queue. +// capacity is used in bytes array allocation +// When verbose flag is set then information about memory allocation are printed +func NewBytesQueue(capacity int, maxCapacity int, verbose bool) *BytesQueue { + return &BytesQueue{ + array: make([]byte, capacity), + capacity: capacity, + maxCapacity: maxCapacity, + headerBuffer: make([]byte, binary.MaxVarintLen32), + tail: leftMarginIndex, + head: leftMarginIndex, + rightMargin: leftMarginIndex, + verbose: verbose, + } +} diff --git a/queue/new_unix.go b/queue/new_unix.go new file mode 100644 index 00000000..762a0aa7 --- /dev/null +++ b/queue/new_unix.go @@ -0,0 +1,57 @@ +//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos || linux || netbsd +// +build aix darwin dragonfly freebsd openbsd solaris zos linux netbsd + +// build tags are sync from: +// golang.org/x/sys@v0.21.0/unix/mmap_nomremap.go +// golang.org/x/sys@v0.21.0/unix/mmap_mremap.go + +package queue + +import ( + "encoding/binary" + + "golang.org/x/sys/unix" +) + +func pageUpper(in uintptr) uintptr { + const pageMask = ((1 << 12) - 1) + return (in + pageMask) &^ (pageMask) +} + +// NewBytesQueue initialize new bytes queue. +// capacity is used in bytes array allocation +// When verbose flag is set then information about memory allocation are printed +func NewBytesQueue(capacity int, maxCapacity int, verbose bool) *BytesQueue { + var array []byte + if maxCapacity != 0 { + var err error + if maxCapacity >= 1<<12 { + array, err = unix.Mmap( + 0, + 0, + int(pageUpper(uintptr(maxCapacity))), + unix.PROT_READ|unix.PROT_WRITE, + unix.MAP_ANON|unix.MAP_PRIVATE, + ) + if err != nil { + panic(err) + } + } else { + array = make([]byte, maxCapacity) + } + capacity = maxCapacity + } else { + array = make([]byte, capacity) + } + + return &BytesQueue{ + array: array, + capacity: capacity, + maxCapacity: maxCapacity, + headerBuffer: make([]byte, binary.MaxVarintLen32), + tail: leftMarginIndex, + head: leftMarginIndex, + rightMargin: leftMarginIndex, + verbose: verbose, + } +}