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

zero out allocated buffers on allocation #21

Merged
merged 1 commit into from
Mar 12, 2024
Merged
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
60 changes: 30 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,36 +126,36 @@ func main() {
Below is a comparative table with the different benchmark results.

```
BenchmarkRuntimeNewObject/100-8 1000000 1009 ns/op 800 B/op 100 allocs/op
BenchmarkRuntimeNewObject/1000-8 117721 9963 ns/op 8000 B/op 1000 allocs/op
BenchmarkRuntimeNewObject/10000-8 10000 100035 ns/op 80000 B/op 10000 allocs/op
BenchmarkRuntimeNewObject/100000-8 1202 1003802 ns/op 800008 B/op 100000 allocs/op
BenchmarkRuntimeNewObject/1000000-8 120 10089223 ns/op 8000086 B/op 1000000 allocs/op
BenchmarkMonotonicArenaNewObject/100-8 1000000 2810 ns/op 800 B/op 86 allocs/op
BenchmarkMonotonicArenaNewObject/1000-8 88327 27757 ns/op 8000 B/op 851 allocs/op
BenchmarkMonotonicArenaNewObject/10000-8 10000 278321 ns/op 80000 B/op 8689 allocs/op
BenchmarkMonotonicArenaNewObject/100000-8 922 2776261 ns/op 800000 B/op 85783 allocs/op
BenchmarkMonotonicArenaNewObject/1000000-8 100 27928883 ns/op 8000001 B/op 868928 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/100-8 5194 223815 ns/op 2018 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/1000-8 4696 230037 ns/op 2232 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/10000-8 3408 345998 ns/op 3076 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/100000-8 729 1618922 ns/op 14383 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/1000000-8 81 14709630 ns/op 129453 B/op 0 allocs/op
BenchmarkRuntimeMakeSlice/100-8 47329 25681 ns/op 204800 B/op 100 allocs/op
BenchmarkRuntimeMakeSlice/1000-8 4420 261322 ns/op 2048010 B/op 1000 allocs/op
BenchmarkRuntimeMakeSlice/10000-8 469 2525088 ns/op 20480097 B/op 10001 allocs/op
BenchmarkRuntimeMakeSlice/100000-8 46 24549537 ns/op 204800932 B/op 100009 allocs/op
BenchmarkRuntimeMakeSlice/1000000-8 4 259382260 ns/op 2048009360 B/op 1000097 allocs/op
BenchmarkMonotonicArenaMakeSlice/100-8 67718 18072 ns/op 204800 B/op 99 allocs/op
BenchmarkMonotonicArenaMakeSlice/1000-8 8508 181105 ns/op 2048000 B/op 993 allocs/op
BenchmarkMonotonicArenaMakeSlice/10000-8 720 1709450 ns/op 20480004 B/op 9928 allocs/op
BenchmarkMonotonicArenaMakeSlice/100000-8 92 17137978 ns/op 204800060 B/op 99444 allocs/op
BenchmarkMonotonicArenaMakeSlice/1000000-8 6 175183750 ns/op 2048000576 B/op 991474 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/100-8 69325 17460 ns/op 204800 B/op 99 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/1000-8 8067 175321 ns/op 2048000 B/op 993 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/10000-8 696 1767369 ns/op 20480012 B/op 9926 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/100000-8 98 17512536 ns/op 204800064 B/op 99478 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/1000000-8 6 174489826 ns/op 2048000624 B/op 991474 allocs/op
BenchmarkRuntimeNewObject/100-8 1310493 909.2 ns/op 800 B/op 100 allocs/op
BenchmarkRuntimeNewObject/1000-8 132147 9030 ns/op 8000 B/op 1000 allocs/op
BenchmarkRuntimeNewObject/10000-8 13296 90249 ns/op 80000 B/op 10000 allocs/op
BenchmarkRuntimeNewObject/100000-8 1316 904476 ns/op 800004 B/op 100000 allocs/op
BenchmarkRuntimeNewObject/1000000-8 130 9033261 ns/op 8000044 B/op 1000000 allocs/op
BenchmarkMonotonicArenaNewObject/100-8 2266246 530.5 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaNewObject/1000-8 228908 5200 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaNewObject/10000-8 23200 51807 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaNewObject/100000-8 2312 519789 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaNewObject/1000000-8 229 5203328 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/100-8 884904 1357 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/1000-8 88495 13526 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/10000-8 8844 135562 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/100000-8 885 1359547 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/1000000-8 87 13591854 ns/op 0 B/op 0 allocs/op
BenchmarkRuntimeMakeSlice/100-8 57231 20169 ns/op 204800 B/op 100 allocs/op
BenchmarkRuntimeMakeSlice/1000-8 5780 206335 ns/op 2048007 B/op 1000 allocs/op
BenchmarkRuntimeMakeSlice/10000-8 585 2017157 ns/op 20480080 B/op 10000 allocs/op
BenchmarkRuntimeMakeSlice/100000-8 57 20167039 ns/op 204800759 B/op 100007 allocs/op
BenchmarkRuntimeMakeSlice/1000000-8 5 200384042 ns/op 2048007507 B/op 1000078 allocs/op
BenchmarkMonotonicArenaMakeSlice/100-8 627627 2219 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaMakeSlice/1000-8 52328 22791 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaMakeSlice/10000-8 3667 312075 ns/op 0 B/op 0 allocs/op
BenchmarkMonotonicArenaMakeSlice/100000-8 164 6971221 ns/op 70582281 B/op 34464 allocs/op
BenchmarkMonotonicArenaMakeSlice/1000000-8 8 128829224 ns/op 1913782512 B/op 934466 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/100-8 157754 8651 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/1000-8 13676 87545 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/10000-8 1358 879413 ns/op 0 B/op 0 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/100000-8 109 10689078 ns/op 70582276 B/op 34464 allocs/op
BenchmarkConcurrentMonotonicArenaMakeSlice/1000000-8 8 133404771 ns/op 1913782680 B/op 934468 allocs/op
```

## Contributing
Expand Down
24 changes: 10 additions & 14 deletions monotonic_arena.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ func (s *monotonicBuffer) alloc(size, alignment uintptr) (unsafe.Pointer, bool)
ptr := unsafe.Pointer(uintptr(s.ptr) + s.offset + alignOffset)
s.offset += allocSize

b := unsafe.Slice((*byte)(ptr), size)

// This piece of code will be translated into a runtime.memclrNoHeapPointers
// invocation by the compiler, which is an assembler optimized implementation.
// Architecture specific code can be found at src/runtime/memclr_$GOARCH.s
// in Go source (since https://codereview.appspot.com/137880043).
for i := range b {
b[i] = 0
}

return ptr, true
}

Expand All @@ -48,20 +58,6 @@ func (s *monotonicBuffer) reset(release bool) {

if release {
s.ptr = nil
} else {
s.zeroOutBuffer()
}
}

func (s *monotonicBuffer) zeroOutBuffer() {
b := unsafe.Slice((*byte)(s.ptr), s.size)

// This piece of code will be translated into a runtime.memclrNoHeapPointers
// invocation by the compiler, which is an assembler optimized implementation.
// Architecture specific code can be found at src/runtime/memclr_$GOARCH.s
// in Go source (since https://codereview.appspot.com/137880043).
for i := range b {
b[i] = 0
}
}

Expand Down
54 changes: 22 additions & 32 deletions monotonic_arena_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ func BenchmarkRuntimeNewObject(b *testing.B) {
for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
a := newRuntimeAllocator[int]()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for j := 0; j < objectCount; j++ {
_ = a.new()
Expand All @@ -140,52 +137,47 @@ func BenchmarkRuntimeNewObject(b *testing.B) {
}

func BenchmarkMonotonicArenaNewObject(b *testing.B) {
for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
monotonicArena := NewMonotonicArena(10*1024*1024, 10) // 10Mb buffer size (100Mb max size)
monotonicArena := NewMonotonicArena(16*1024*1024, 8) // 16Mb buffer size (128Mb max size)

a := newArenaAllocator[int](monotonicArena)
a := newArenaAllocator[int](monotonicArena)

for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for j := 0; j < objectCount; j++ {
_ = a.new()
}
monotonicArena.Reset(false)
}
})
}
}

func BenchmarkConcurrentMonotonicArenaNewObject(b *testing.B) {
for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
monotonicArena := NewMonotonicArena(10*1024*1024, 10) // 10Mb buffer size (100Mb max size)
monotonicArena := NewMonotonicArena(16*1024*1024, 8) // 16Mb buffer size (128Mb max size)

a := newArenaAllocator[int](NewConcurrentArena(monotonicArena))
a := newArenaAllocator[int](NewConcurrentArena(monotonicArena))

for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for j := 0; j < objectCount; j++ {
_ = a.new()
}
a.(*arenaAllocator[int]).a.Reset(false)
monotonicArena.Reset(false)
}
})
}
}

func BenchmarkRuntimeMakeSlice(b *testing.B) {
a := newRuntimeAllocator[int]()

for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
a := newRuntimeAllocator[int]()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for j := 0; j < objectCount; j++ {
_ = a.makeSlice(0, 256)
Expand All @@ -196,38 +188,36 @@ func BenchmarkRuntimeMakeSlice(b *testing.B) {
}

func BenchmarkMonotonicArenaMakeSlice(b *testing.B) {
for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
monotonicArena := NewMonotonicArena(10*1024*1024, 10) // 10Mb buffer size (100Mb max size)
monotonicArena := NewMonotonicArena(16*1024*1024, 8) // 16Mb buffer size (128Mb max size)

a := newArenaAllocator[int](monotonicArena)
a := newArenaAllocator[int](monotonicArena)

for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for j := 0; j < objectCount; j++ {
_ = a.makeSlice(0, 256)
}
monotonicArena.Reset(false)
}
})
}
}

func BenchmarkConcurrentMonotonicArenaMakeSlice(b *testing.B) {
for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
monotonicArena := NewMonotonicArena(10*1024*1024, 10) // 10Mb buffer size (100Mb max size)
monotonicArena := NewMonotonicArena(16*1024*1024, 8) // 16Mb buffer size (128Mb max size)

a := newArenaAllocator[int](NewConcurrentArena(monotonicArena))
a := newArenaAllocator[int](NewConcurrentArena(monotonicArena))

for _, objectCount := range []int{100, 1_000, 10_000, 100_000, 1_000_000} {
b.Run(fmt.Sprintf("%d", objectCount), func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for j := 0; j < objectCount; j++ {
_ = a.makeSlice(0, 256)
}
monotonicArena.Reset(false)
}
})
}
Expand Down
Loading