高吞吐实践
客户端每次从桶中读取数据的大小,通过配置项
fs.ofs.block.memory.trunk.byte
进行控制。配置项 | 配置项内容 | 说明 |
fs.ofs.block.memory.trunk.byte | 1048576 | 对象块大小,单位为字节,默认值1048576,即1MB |
说明:
在高吞吐场景中,客户端引入了预读块逻辑,将一个文件拆分为多个预读块,缓存至内存中,降低读取时延,提升吞吐。您可以通过指定预读块的参数,满足不同场景的吞吐需求。
顺序读场景
客户端内部会通过游标检测当前的场景是否为顺序读,若为顺序读场景,则会启用预读逻辑,否则不会使用。预读逻辑中,客户端会固定每次缓存的预读块个数,相关配置项如下,您可以根据机型配置进行相关的参数调优。
配置项 | 配置项内容 | 说明 |
fs.ofs.prev.read.block.count | 16 | 预读块的个数,默认值为16 |
fs.ofs.prev.read.block.release.enable | true | 是否从内存中释放已读完的块,默认值为 true |
fs.ofs.block.max.read.memory.cache.mb | 16 | 单个文件可用内存量,默认值为16,单位为 MB 说明: 为避免 OOM,您可以参考下文内存使用实践,控制全局 cache 模型。 |
fs.ofs.data.transfer.thread.count | 32 | 从桶中拉取预读块的 IO 线程池核心线程数 |
fs.ofs.data.transfer.max.thread.count | Integer.MAX_VALUE | IO 线程池最大线程数 |
随机读场景
如上文所说,客户端会检测当前场景,若为随机读,则不会触发预读逻辑。另外,此场景下,建议您根据实际业务场景,调整配置项
fs.ofs.block.memory.trunk.byte
,修改每次读取 COS 桶的数据大小,避免随机读场景中的读放大。
客户端内存使用实践
上传:使用内存 cache + 磁盘 cache
下载:只会使用内存 cache
其中,内存 cache 块是按需申请的, 优先申请内存 cache 块, 当内存 cache 块不足后,会申请磁盘 cache 块。磁盘 cache 在写入数据过程中会使用堆外内存,以减少堆内内存与内核态的内存之间的 copy,从而提升写入数据的性能。
为避免多个文件互相影响(例如某个文件未关闭,资源未释放时,导致新的读写无法打开),SDK 总体默认原则是控制单个文件使用的 cache 数量。同时,为避免 OOM 问题,客户端提供全局(文件系统粒度)的缓存配置项,您可以根据客户端环境调整配置,以实现最优性能。
单文件 cache 控制模型
OFS SDK 使用以下两个配置项分别控制单个文件的 cache 使用量:
配置项 | 配置项内容 | 说明 |
fs.ofs.block.max.memory.cache.mb | 16 | 内存 cache 使用量,默认值为16,单位为 MB |
fs.ofs.block.max.file.cache.mb | 256 | 磁盘 cache 使用量,默认值为256,单位为 MB |
说明:
全局(文件系统粒度)cache 控制模型
SDK 提供对于读、写两种请求的全局(文件系统粒度)cache 控制,以规避 OOM 问题。具体说明如下:
配置项 | 配置项内容 | 说明 |
fs.ofs.block.total.memory.cache.mb | 0 | 上传最大内存使用量,默认值为0(不控制),单位 MB |
fs.ofs.block.total.memory.cache.percent | 100 | 上传最大内存使用比例,默认值为100,单位为百分比 |
fs.ofs.block.total.memory.jvm.heap.percent | 0 | 最大 JVM 内存使用比例,默认值为0(不控制),单位为百分比 |
SDK 共提供两种全局控制:
规则1:通过
fs.ofs.block.total.memory.cache.mb
与 fs.ofs.block.total.memory.cache.percent
控制上传最大内存使用量。配置后,最大使用的内存大小为:fs.ofs.block.total.memory.cache.mb
* fs.ofs.block.total.memory.cache.percent
/ 100。当配置后,SDK 会根据算出的全局内存 cache 大小 / 单个文件最大大小 fs.ofs.block.max.memory.cache.mb
,计算出能同时写入的文件量,以此来分配信号。新打开文件时候,会申请1个信号量,当申请失败后,会强制使用磁盘 cache。 当文件关闭时候,会归还信号量。 规则2:通过 fs.ofs.block.total.memory.jvm.heap.percent 控制最大 JVM 内存。配置后,SDK 会获取 JVM 最大内存
(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax())
* fs.ofs.block.total.memory.jvm.heap.percent
/ 100 来确定。
默认情况下,
fs.ofs.block.total.memory.cache.mb
与 fs.ofs.block.total.memory.jvm.heap.percent
值为0,即不会对内存进行任何控制。若两个配置项均为非0,则规则1(最大内存使用量)优先级高于规则2(最大 JVM 内存使用量)。配置项 | 配置项内容 | 说明 |
fs.ofs.block.total.read.memory.cache.mb | 0 | 下载最大内存使用量,默认值为0(不控制),单位 MB |
fs.ofs.block.total.read.memory.cache.percent | 100 | 下载最大内存使用比例,默认值为100,单位为百分比 |
SDK 通过
fs.ofs.block.total.read.memory.cache.mb
与 fs.ofs.block.total.read.memory.cache.percent
控制下载最大内存使用量。配置后,最大使用的内存大小为:fs.ofs.block.total.read.memory.cache.mb
* fs.ofs.block.total.read.memory.cache.percent
/ 100。当配置后,SDK 会根据算出的全局内存 cache 大小 / 单个文件最大大小 fs.ofs.block.max.memory.cache.mb
,计算出能同时写入的文件量,以此来分配信号。新打开文件时候,会申请1个信号量,当申请失败后,会强制使用磁盘 cache。 当文件关闭时候,会归还信号量。申请通过队列实现阻塞机制的,当信号量不足时候,会等待其他文件关闭释放信号量。