Skip to content

Commit 70694a8

Browse files
committed
add a benchmark
1 parent f39bc3b commit 70694a8

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package block
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/e2b-dev/infra/packages/shared/pkg/storage/header"
8+
)
9+
10+
// BenchmarkDirtyTracking benchmarks the dirty tracking operations
11+
// which were changed from sync.Map to bitset.BitSet.
12+
func BenchmarkDirtyTracking(b *testing.B) {
13+
const (
14+
blockSize = int64(header.PageSize) // 4KB blocks
15+
cacheSize = 1024 * 1024 * 1024 // 1GB cache = 262144 blocks
16+
)
17+
18+
tmpFile := b.TempDir() + "/bench_cache"
19+
20+
cache, err := NewCache(cacheSize, blockSize, tmpFile, false)
21+
if err != nil {
22+
b.Fatalf("failed to create cache: %v", err)
23+
}
24+
defer cache.Close()
25+
26+
// Simulate write data
27+
data := make([]byte, blockSize)
28+
29+
b.Run("SetIsCached", func(b *testing.B) {
30+
b.ReportAllocs()
31+
b.ResetTimer()
32+
33+
for i := 0; i < b.N; i++ {
34+
// Simulate marking a block as cached
35+
off := int64(i%262144) * blockSize
36+
cache.setIsCached(off, blockSize)
37+
}
38+
})
39+
40+
b.Run("IsCached_Hit", func(b *testing.B) {
41+
// Pre-populate some blocks as cached
42+
for i := int64(0); i < 1000; i++ {
43+
cache.setIsCached(i*blockSize, blockSize)
44+
}
45+
46+
b.ReportAllocs()
47+
b.ResetTimer()
48+
49+
for i := 0; i < b.N; i++ {
50+
off := int64(i%1000) * blockSize
51+
cache.isCached(off, blockSize)
52+
}
53+
})
54+
55+
b.Run("IsCached_Miss", func(b *testing.B) {
56+
b.ReportAllocs()
57+
b.ResetTimer()
58+
59+
for i := 0; i < b.N; i++ {
60+
// Check blocks that are definitely not cached (high offsets)
61+
off := int64(100000+i%100000) * blockSize
62+
cache.isCached(off, blockSize)
63+
}
64+
})
65+
66+
b.Run("WriteAt_SingleBlock", func(b *testing.B) {
67+
b.ReportAllocs()
68+
b.ResetTimer()
69+
70+
for i := 0; i < b.N; i++ {
71+
off := int64(i%262144) * blockSize
72+
cache.WriteAt(data, off)
73+
}
74+
})
75+
76+
b.Run("WriteAt_MultiBlock", func(b *testing.B) {
77+
// Write spanning 4 blocks
78+
multiBlockData := make([]byte, blockSize*4)
79+
80+
b.ReportAllocs()
81+
b.ResetTimer()
82+
83+
for i := 0; i < b.N; i++ {
84+
off := int64(i%65536) * blockSize * 4
85+
cache.WriteAt(multiBlockData, off)
86+
}
87+
})
88+
}
89+
90+
// BenchmarkDirtySortedKeys benchmarks the dirtySortedKeys operation
91+
// used during export.
92+
func BenchmarkDirtySortedKeys(b *testing.B) {
93+
const (
94+
blockSize = int64(header.PageSize)
95+
cacheSize = 1024 * 1024 * 1024 // 1GB
96+
)
97+
98+
tmpFile := b.TempDir() + "/bench_cache"
99+
100+
cache, err := NewCache(cacheSize, blockSize, tmpFile, false)
101+
if err != nil {
102+
b.Fatalf("failed to create cache: %v", err)
103+
}
104+
defer cache.Close()
105+
106+
// Mark 10% of blocks as dirty (26214 blocks)
107+
for i := int64(0); i < 26214; i++ {
108+
cache.setIsCached(i*blockSize, blockSize)
109+
}
110+
111+
b.Run("DirtySortedKeys_10pct", func(b *testing.B) {
112+
b.ReportAllocs()
113+
b.ResetTimer()
114+
115+
for i := 0; i < b.N; i++ {
116+
keys := cache.dirtySortedKeys()
117+
_ = keys
118+
}
119+
})
120+
}
121+
122+
// BenchmarkCacheCreation benchmarks cache creation overhead.
123+
func BenchmarkCacheCreation(b *testing.B) {
124+
const (
125+
blockSize = int64(header.PageSize)
126+
)
127+
128+
sizes := []int64{
129+
1 * 1024 * 1024, // 1MB
130+
100 * 1024 * 1024, // 100MB
131+
1024 * 1024 * 1024, // 1GB
132+
10 * 1024 * 1024 * 1024, // 10GB
133+
}
134+
135+
for _, size := range sizes {
136+
name := formatSize(size)
137+
b.Run(name, func(b *testing.B) {
138+
b.ReportAllocs()
139+
b.ResetTimer()
140+
141+
for i := 0; i < b.N; i++ {
142+
tmpFile := b.TempDir() + "/bench_cache"
143+
cache, err := NewCache(size, blockSize, tmpFile, false)
144+
if err != nil {
145+
b.Fatalf("failed to create cache: %v", err)
146+
}
147+
cache.Close()
148+
os.RemoveAll(tmpFile)
149+
}
150+
})
151+
}
152+
}
153+
154+
func formatSize(bytes int64) string {
155+
const (
156+
KB = 1024
157+
MB = 1024 * KB
158+
GB = 1024 * MB
159+
)
160+
161+
switch {
162+
case bytes >= GB:
163+
return string(rune('0'+bytes/GB)) + "GB"
164+
case bytes >= MB:
165+
return string(rune('0'+bytes/MB)) + "MB"
166+
default:
167+
return string(rune('0'+bytes/KB)) + "KB"
168+
}
169+
}

0 commit comments

Comments
 (0)