Skip to content

Commit 2af4396

Browse files
Update the README to put more emphasis on situations where internal caches can lead to leaks if not used properly.
1 parent 1dba7f2 commit 2af4396

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,56 @@ type FixedArray struct {
124124
- Validate data sizes before processing
125125

126126
3. **Performance Optimization**
127+
127128
- Reuse structs when possible
128129
- Consider using pools for frequently used structures
129130

131+
4. **Memory Management**
132+
133+
- The library uses internal 4K buffers for efficient unpacking
134+
- When unpacking, slice/string fields in your struct will directly reference these internal buffers
135+
- These buffers will remain in memory as long as your struct fields reference them
136+
- Example of memory retention:
137+
138+
```go
139+
type Message struct {
140+
Data []byte // This field will reference the internal buffer
141+
}
142+
143+
func processRetain() {
144+
messages := make([]*Message, 0)
145+
146+
// Each unpacked message's Data field references the internal buffer
147+
for i := 0; i < 10; i++ {
148+
msg := &Message{}
149+
struc.Unpack(reader, msg)
150+
messages = append(messages, msg)
151+
// The internal buffer can't be GC'ed because msg.Data references it
152+
}
153+
}
154+
```
155+
156+
- To release the internal buffer reference, you can either set the field to nil or copy the data:
157+
158+
```go
159+
func processRelease() {
160+
msg := &Message{}
161+
struc.Unpack(reader, msg)
162+
163+
// Method 1: Simply set to nil if you don't need the data anymore
164+
msg.Data = nil // Now msg.Data is nil, no longer references the internal buffer
165+
166+
// Method 2: Copy data if you need to keep it
167+
if needData {
168+
dataCopy := make([]byte, len(msg.Data))
169+
copy(dataCopy, msg.Data)
170+
msg.Data = dataCopy // Now msg.Data references our copy
171+
}
172+
173+
// The internal buffer can now be GC'ed if no other structs reference it
174+
}
175+
```
176+
130177
## Performance Benchmarks
131178

132179
```

README_CN.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,56 @@ type FixedArray struct {
124124
- 在处理之前验证数据大小
125125

126126
3. **性能优化**
127+
127128
- 尽可能重用结构体
128129
- 考虑对频繁使用的结构使用对象池
129130

131+
4. **内存管理**
132+
133+
- 库使用内部 4K 缓冲区来实现高效解包
134+
- 解包时,结构体中的切片/字符串字段会直接引用这些内部缓冲区
135+
- 只要您的结构体字段还在引用这些缓冲区,它们就会保留在内存中
136+
- 内存保留示例:
137+
138+
```go
139+
type Message struct {
140+
Data []byte // 这个字段会引用内部缓冲区
141+
}
142+
143+
func processRetain() {
144+
messages := make([]*Message, 0)
145+
146+
// 每个解包的消息的 Data 字段都引用内部缓冲区
147+
for i := 0; i < 10; i++ {
148+
msg := &Message{}
149+
struc.Unpack(reader, msg)
150+
messages = append(messages, msg)
151+
// 内部缓冲区无法被 GC,因为 msg.Data 引用着它
152+
}
153+
}
154+
```
155+
156+
- 要释放对内部缓冲区的引用,您可以将字段设为 nil 或复制数据:
157+
158+
```go
159+
func processRelease() {
160+
msg := &Message{}
161+
struc.Unpack(reader, msg)
162+
163+
// 方法1:如果不再需要数据,直接设为 nil
164+
msg.Data = nil // 现在 msg.Data 为 nil,不再引用内部缓冲区
165+
166+
// 方法2:如果需要保留数据,进行复制
167+
if needData {
168+
dataCopy := make([]byte, len(msg.Data))
169+
copy(dataCopy, msg.Data)
170+
msg.Data = dataCopy // 现在 msg.Data 引用我们的副本
171+
}
172+
173+
// 如果没有其他结构体引用,内部缓冲区现在可以被 GC 了
174+
}
175+
```
176+
130177
## 性能基准测试
131178

132179
```

0 commit comments

Comments
 (0)