Skip to content

Commit 36c81e0

Browse files
Updated the README content with a more detailed explanation of the memory management section.
1 parent 2af4396 commit 36c81e0

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

README.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,16 @@ type FixedArray struct {
130130

131131
4. **Memory Management**
132132

133-
- The library uses internal 4K buffers for efficient unpacking
133+
- When packing, the library pre-allocates a buffer with the exact size needed for the data
134+
135+
```go
136+
bufferSize := packer.Sizeof(value, options)
137+
buffer := make([]byte, bufferSize)
138+
```
139+
140+
- For unpacking, the library uses internal 4K buffers for efficient operations
134141
- When unpacking, slice/string fields in your struct will directly reference these internal buffers
135142
- These buffers will remain in memory as long as your struct fields reference them
136-
- Example of memory retention:
137143

138144
```go
139145
type Message struct {
@@ -143,12 +149,31 @@ type FixedArray struct {
143149
func processRetain() {
144150
messages := make([]*Message, 0)
145151
152+
// >> Important:
153+
// The Field struct is just a metadata description object
154+
// Its lifecycle end does not affect user struct fields that have been set via unsafe operations
155+
// Because unsafe operations have directly modified the underlying pointer of user struct fields to point to the 4K buffer
156+
// >> Therefore:
157+
// Releasing the Field struct will not cause the slice references on the 4K buffer to disappear
158+
// These references only disappear when the user structs using these slices are GC'ed
159+
// The 4K buffer's lifecycle depends on the lifecycle of all user structs referencing it
160+
146161
// Each unpacked message's Data field references the internal buffer
147162
for i := 0; i < 10; i++ {
148163
msg := &Message{}
164+
// During unpacking:
165+
// 1. unpackBasicTypeSlicePool provides 4K buffer
166+
// 2. Field struct handles metadata
167+
// 3. unsafe operations point msg.Data to part of 4K buffer
149168
struc.Unpack(reader, msg)
169+
// Even if Field struct is released now
170+
// msg.Data still points to 4K buffer
171+
// Only when msg is GC'ed will this reference disappear
150172
messages = append(messages, msg)
151-
// The internal buffer can't be GC'ed because msg.Data references it
173+
// Internal buffer can't be GC'ed because msg.Data references it
174+
// Field struct's lifecycle is irrelevant to 4K buffer references
175+
// 4K buffer references are held by user structs
176+
// Only when all user structs referencing this 4K buffer are GC'ed can the buffer be collected
152177
}
153178
}
154179
```

README_CN.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,16 @@ type FixedArray struct {
130130

131131
4. **内存管理**
132132

133-
- 库使用内部 4K 缓冲区来实现高效解包
133+
- 库在打包时,会根据数据大小预分配精确大小的缓冲区
134+
135+
```go
136+
bufferSize := packer.Sizeof(value, options)
137+
buffer := make([]byte, bufferSize)
138+
```
139+
140+
- 解包时,库使用内部 4K 缓冲区来实现高效解包
134141
- 解包时,结构体中的切片/字符串字段会直接引用这些内部缓冲区
135142
- 只要您的结构体字段还在引用这些缓冲区,它们就会保留在内存中
136-
- 内存保留示例:
137143

138144
```go
139145
type Message struct {
@@ -143,12 +149,31 @@ type FixedArray struct {
143149
func processRetain() {
144150
messages := make([]*Message, 0)
145151
152+
// >> 重要的是:
153+
// Field 结构体只是一个元数据描述对象
154+
// 它的生命周期结束与否并不影响已经通过 unsafe 操作设置的用户结构体字段
155+
// 因为 unsafe 操作已经直接修改了用户结构体字段的底层指针,指向了 4K buffer
156+
// >> 所以:
157+
// Field 结构体的释放并不会导致 4K buffer 上的切片引用消失
158+
// 只有当使用这些切片的用户结构体被 GC 时,这些引用才会消失
159+
// 4K buffer 的生命周期取决于所有引用它的用户结构体的生命周期
160+
146161
// 每个解包的消息的 Data 字段都引用内部缓冲区
147162
for i := 0; i < 10; i++ {
148163
msg := &Message{}
164+
// 解包过程中:
165+
// 1. unpackBasicTypeSlicePool 提供 4K buffer
166+
// 2. Field 结构体处理元数据
167+
// 3. unsafe 操作将 msg.Data 指向 4K buffer 的一部分
149168
struc.Unpack(reader, msg)
169+
// 这时即使 Field 结构体被释放
170+
// msg.Data 仍然指向 4K buffer
171+
// 只有当 msg 被 GC,这个引用才会消失
150172
messages = append(messages, msg)
151173
// 内部缓冲区无法被 GC,因为 msg.Data 引用着它
174+
// Field 结构体的生命周期与 4K buffer 的引用无关
175+
// 4K buffer 的引用由用户结构体持有
176+
// 只有当所有引用这个 4K buffer 的用户结构体都被 GC 时,这个 buffer 才可能被回收
152177
}
153178
}
154179
```

0 commit comments

Comments
 (0)