diff --git a/pkg/common/malloc/c_allocator.go b/pkg/common/malloc/c_allocator.go index bf7b788dc6601..7d0c50ad34af3 100644 --- a/pkg/common/malloc/c_allocator.go +++ b/pkg/common/malloc/c_allocator.go @@ -16,7 +16,10 @@ package malloc -import "unsafe" +import ( + "sync/atomic" + "unsafe" +) /* #include @@ -25,24 +28,39 @@ import "C" type CAllocator struct { deallocatorPool *ClosureDeallocatorPool[cDeallocatorArgs, *cDeallocatorArgs] + bytesFree atomic.Uint64 } type cDeallocatorArgs struct { - ptr unsafe.Pointer + ptr unsafe.Pointer + size uint64 } func (cDeallocatorArgs) As(Trait) bool { return false } -func NewCAllocator() *CAllocator { - return &CAllocator{ +const ( + cMallocReturnToOSThreshold = 64 * MB +) + +func NewCAllocator() (ret *CAllocator) { + ret = &CAllocator{ deallocatorPool: NewClosureDeallocatorPool( func(hints Hints, args *cDeallocatorArgs) { C.free(args.ptr) + + n := ret.bytesFree.Add(args.size) + if n > cMallocReturnToOSThreshold { + ret.bytesFree.Store(0) + // return memory to OS + returnMallocMemoryToOS() + } + }, ), } + return } var _ Allocator = new(CAllocator) @@ -54,6 +72,7 @@ func (c *CAllocator) Allocate(size uint64, hints Hints) ([]byte, Deallocator, er } slice := unsafe.Slice((*byte)(ptr), size) return slice, c.deallocatorPool.Get(cDeallocatorArgs{ - ptr: ptr, + ptr: ptr, + size: size, }), nil } diff --git a/pkg/common/malloc/c_allocator_darwin.go b/pkg/common/malloc/c_allocator_darwin.go new file mode 100644 index 0000000000000..f041b047ec700 --- /dev/null +++ b/pkg/common/malloc/c_allocator_darwin.go @@ -0,0 +1,20 @@ +// Copyright 2024 Matrix Origin +// +// 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. + +//go:build cgo + +package malloc + +func returnMallocMemoryToOS() { +} diff --git a/pkg/common/malloc/c_allocator_linux.go b/pkg/common/malloc/c_allocator_linux.go new file mode 100644 index 0000000000000..7b1e0ad9b4ac1 --- /dev/null +++ b/pkg/common/malloc/c_allocator_linux.go @@ -0,0 +1,33 @@ +// Copyright 2024 Matrix Origin +// +// 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. + +//go:build cgo + +package malloc + +/* +#include +#include +*/ +import "C" + +func init() { + // malloc tunings + C.mallopt(C.M_TOP_PAD, 0) // no sbrk padding + C.mallopt(C.M_MMAP_THRESHOLD, 0) // always use mmap +} + +func returnMallocMemoryToOS() { + C.malloc_trim(0) +} diff --git a/pkg/common/malloc/c_allocator_test.go b/pkg/common/malloc/c_allocator_test.go index c0e32ada10ad0..9b07355c4e96a 100644 --- a/pkg/common/malloc/c_allocator_test.go +++ b/pkg/common/malloc/c_allocator_test.go @@ -35,3 +35,12 @@ func FuzzCAllocator(f *testing.F) { return NewCAllocator() }) } + +func TestCAllocatorReturnToOSThreshold(t *testing.T) { + allocator := NewCAllocator() + _, dec, err := allocator.Allocate(cMallocReturnToOSThreshold*2, NoHints) + if err != nil { + t.Fatal(err) + } + dec.Deallocate(NoHints) +} diff --git a/pkg/common/malloc/default.go b/pkg/common/malloc/default.go index e423a5169ba22..41e5e32b923c0 100644 --- a/pkg/common/malloc/default.go +++ b/pkg/common/malloc/default.go @@ -74,7 +74,7 @@ func newDefault(delta *Config) (allocator Allocator) { }() if config.Allocator == nil { - config.Allocator = ptrTo("mmap") + config.Allocator = ptrTo("c") } switch strings.ToLower(*config.Allocator) { diff --git a/pkg/common/malloc/utils.go b/pkg/common/malloc/utils.go index ccd91392486a6..00e85615882fd 100644 --- a/pkg/common/malloc/utils.go +++ b/pkg/common/malloc/utils.go @@ -15,6 +15,7 @@ package malloc const ( + KB = 1 << 10 MB = 1 << 20 GB = 1 << 30 )