零拷贝
学习如何在 Solana 程序中使用 Anchor 的零拷贝反序列化功能来处理大型账户数据。
使用方法
零拷贝是一种反序列化功能,允许程序直接从内存中读取账户数据而无需复制。这在处理大型账户时特别有用。
要使用零拷贝,请将 bytemuck
crate 添加到你的依赖项中。添加 min_const_generics
功能以允许在你的零拷贝类型中使用任意大小的数组。
定义零拷贝账户
要定义使用零拷贝的账户类型,请使用 #[account(zero_copy)]
注解结构体。
#[account(zero_copy)]
属性自动实现了零拷贝反序列化所需的几个特性:
使用 AccountLoader 处理零拷贝账户
要反序列化一个零拷贝账户,请使用 AccountLoader<'info, T>
,其中 T
是使用 #[account(zero_copy)]
属性定义的零拷贝账户类型。
例如:
初始化零拷贝账户
init
约束可以与 AccountLoader
类型一起使用来创建零拷贝账户。
由于 CPI 限制,init
约束最多只能分配 10240 字节。在底层,init
约束会调用 SystemProgram 创建账户。
首次初始化零拷贝账户时,使用 load_init
获取账户数据的可变引用。load_init
方法还会设置账户标识符。
对于需要超过 10240 字节的账户,请使用 zero
约束而不是 init
。zero
约束通过检查账户标识符是否已设置来验证账户是否未初始化。
使用 zero
约束时,你需要先在单独的指令中通过直接调用 System Program 来创建账户。这允许你创建最大为 Solana 最大账户大小 10MB (10_485_760 字节) 的账户,绕过了 CPI 的限制。
和之前一样,使用 load_init
获取账户数据的可变引用并设置账户标识符。由于 8 字节保留给账户标识符,最大数据大小为 10_485_752 字节 (10MB - 8 字节)。
更新零拷贝账户
当你需要可变访问来更新现有的零拷贝账户时,使用 load_mut
:
读取零拷贝账户
使用 load
仅读取账户数据。
示例
以下示例展示了在 Anchor 中初始化零拷贝账户的两种方法:
- 使用
init
约束在单个指令中初始化账户 - 使用
zero
约束初始化数据大于 10240 字节的账户
零拷贝
初始化大型账户
当初始化一个需要超过 10,240 字节空间的账户时,你必须将初始化过程分为两步:
- 在单独的指令中调用 System Program 创建账户
- 在你的程序指令中初始化账户数据
注意,Solana 的最大账户大小为 10MB (10_485_760 字节),8 字节保留给账户标识符。