Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable mmap to alloc on unix-like system #397

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/allegro/bigcache/v3

go 1.16
go 1.17

require golang.org/x/sys v0.1.0
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
16 changes: 0 additions & 16 deletions queue/bytes_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 12 additions & 3 deletions queue/bytes_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -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
}
}
22 changes: 22 additions & 0 deletions queue/new_others.go
Original file line number Diff line number Diff line change
@@ -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,
}
}
57 changes: 57 additions & 0 deletions queue/new_unix.go
Original file line number Diff line number Diff line change
@@ -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,
}
}