Ubuntu下R读取挂载NAS存储asc栅格文件速度异常缓慢问题
问题背景
局域网部署NAS存储各类栅格数据,测试环境如下:
- 设备1:Ubuntu系统台式机,1Gbps有线以太网接入局域网
- 设备2:Windows 10系统笔记本,WiFi 5接入局域网
两台设备通过R语言访问NAS存储的栅格数据,本地SSD存储同份数据时,两台设备执行相同读取任务耗时均低于0.4秒,符合本地存储性能预期;除R读取特定格式栅格的场景外,两台设备其余网络任务性能均正常,同网络环境下可稳定复现异常。
测试1:NetCDF格式文件读取
测试代码如下:
library(ncdf4) library(raster) a1<-Sys.time() setwd(..nas_path..) a<-list.files() for (i in 1:24){ q1<-nc_open(a[1]) q0<-raster(a[1],varname="wind_speed",band=i)/100 nc_close(q1) } a2<-Sys.time() a2-a1
测试结果:
- Ubuntu有线环境:耗时18秒
- Windows WiFi环境:耗时32秒
该结果与网络带宽性能预期一致
测试2:ASC格式文件读取
测试代码如下:
library(raster) setwd(..nas_path..) a<-list.files() a1<-Sys.time() for (i in 1:24){ q1<-raster(a[i]) } a2<-Sys.time() a2-a1
测试结果:
- Ubuntu有线环境:耗时1.9分钟
- Windows WiFi环境:耗时3.2秒
该结果完全偏离性能预期:按带宽推算Ubuntu读取速度应为Windows的2倍左右,实际Windows读取速度是Ubuntu的近40倍
补充说明:多组重复基准测试验证了该结果的稳定性,时间统计单位均为秒,测试顺序、单次数值波动不影响最终结论。
异常原因
该问题由Ubuntu默认SMB/CIFS挂载配置的缓存策略,与raster包读取ASC文件的IO模式不匹配导致,具体逻辑如下:
- ASC是纯文本栅格格式,raster包读取ASC文件时不会发起连续的大尺寸顺序读请求,而是会产生大量碎片化的极小随机读请求:先多次小范围读取文件头解析元数据,再按栅格块偏移做随机寻址读取,单文件读取过程会产生数千到数万次不等的小块IO请求。
- Windows访问SMB共享(NAS默认共享协议)时,默认开启大粒度文件预读、小IO自动合并机制,会把这类碎片化的小读请求批量合并,提前将对应文件块拉取到本地缓存,哪怕是WiFi连接,这类小IO场景的处理效率也极高。
- Ubuntu默认挂载SMB共享时采用
cache=strict配置,预读窗口尺寸极小,不会对碎片化随机小IO做合并和预读处理,每一次小读请求都会单独产生网络往返开销。1Gbps网络下单次网络往返延迟约1ms,数万次请求累积下来的耗时就会达到分钟级,和观测到的现象完全吻合。 - 读取NetCDF格式时,raster包采用大粒度顺序读逻辑,不会触发海量小IO开销,因此两个系统下的性能表现完全符合带宽预期;本地存储的随机IO延迟极低,哪怕是碎片化小请求也不会产生明显耗时,因此本地读取速度正常。
修复方案
Ubuntu挂载NAS的SMB共享时,追加以下挂载参数即可解决问题:cache=loose,rsize=1048576,wsize=1048576,actimeo=1
重新挂载后再执行ASC读取测试,性能会回到与Windows同量级、甚至因有线带宽更高超过Windows的水平。
注意:不建议在该场景下用NFS协议挂载NAS,NFS默认的属性缓存、小IO调度策略比默认配置的SMB表现更差,也会出现类似的慢读问题。
内容的提问来源于stack exchange,提问作者testversion
相关产品推荐
相关产品推荐

