零拷贝序列化
零拷贝序列化允许大型二进制数据(字节数组、数值数组)以带外方式序列化,避免内存复制并减少序列化开销。
何时使用零拷贝
在以下情况下使用零拷贝序列化:
- 序列化大型字节数组或二进制数据块
- 处理数值数组(int[]、double[] 等)
- 通过高性能网络传输数据
- 内存效率至关重要
工作原理
- 序列化:大型缓冲区被提取出来,并通过回调单独返回
- 传输:主序列化数据和缓冲区对象分别传输
- 反序列化:提供缓冲区以重建原始对象
这避免了将大型数据复制到主序列化缓冲区中。
Java
import org.apache.fory.*;
import org.apache.fory.config.*;
import org.apache.fory.serializer.BufferObject;
import org.apache.fory.memory.MemoryBuffer;
import java.util.*;
import java.util.stream.Collectors;
public class ZeroCopyExample {
public static void main(String[] args) {
Fory fory = Fory.builder().withLanguage(Language.XLANG).build();
// 包含大型数组的数据
List<Object> list = List.of(
"str",
new byte[1000], // 大型字节数组
new int[100], // 大型 int 数组
new double[100] // 大型 double 数组
);
// 在序列化期间收集缓冲区对象
Collection<BufferObject> bufferObjects = new ArrayList<>();
byte[] bytes = fory.serialize(list, e -> !bufferObjects.add(e));
// 转换为缓冲区以便传输
List<MemoryBuffer> buffers = bufferObjects.stream()
.map(BufferObject::toBuffer)
.collect(Collectors.toList());
// 使用缓冲区反序列化
Object result = fory.deserialize(bytes, buffers);
System.out.println(result);
}
}
Python
import array
import pyfory
import numpy as np
fory = pyfory.Fory()
# 包含大型数组的数据
data = [
"str",
bytes(bytearray(1000)), # 大型字节数组
array.array("i", range(100)), # 大型 int 数组
np.full(100, 0.0, dtype=np.double) # 大型 numpy 数组
]
# 在序列化期间收集缓冲区对象
serialized_objects = []
serialized_data = fory.serialize(data, buffer_callback=serialized_objects.append)
# 转换为缓冲区以便传输
buffers = [obj.to_buffer() for obj in serialized_objects]
# 使用缓冲区反序列化
result = fory.deserialize(serialized_data, buffers=buffers)
print(result)
Go
package main
import forygo "github.com/apache/fory/go/fory"
import "fmt"
func main() {
fory := forygo.NewFory()
// 包含大型数组的数据
list := []interface{}{
"str",
make([]byte, 1000), // 大型字节数组
}
buf := fory.NewByteBuffer(nil)
var bufferObjects []fory.BufferObject
// 在序列化期间收集缓冲区对象
fory.Serialize(buf, list, func(o fory.BufferObject) bool {
bufferObjects = append(bufferObjects, o)
return false
})
// 转换为缓冲区以便传输
var buffers []*fory.ByteBuffer
for _, o := range bufferObjects {
buffers = append(buffers, o.ToBuffer())
}
// 使用缓冲区反序列化
var newList []interface{}
if err := fory.Deserialize(buf, &newList, buffers); err != nil {
panic(err)
}
fmt.Println(newList)
}
JavaScript
// 零拷贝支持即将推出