- 存储
【免费下载链接】goofys
a high-performance, POSIX-ish Amazon S3 file system written in Go
本文基于 goofys 仓库中的 Azure 基准测试文档 与配套的 原始测试数据,完整还原 goofys 挂载 Azure Blob Storage 时的性能评估全过程:测试跑在什么硬件与地域、如何用一条 Docker 命令复现、benchmark 覆盖哪些文件系统操作、goofys 与 blobfuse 的实测耗时对比,以及这些测试指标背后的脚本实现和 goofys 的 Azure 后端源码。读完本文,你将能独立复跑该基准测试,并理解每一条测试指标的真实含义。
测试环境与前提
文档明确给出了本次 Azure 基准测试的硬件与网络前提,这是理解所有数据的先决条件:
- 计算实例:
Standard DS4 v2(Azure 通用型虚拟机,8 vCPU / 28 GiB 内存级别); - 部署地域:
West US,被测 bucket 同样位于West US,即客户端与服务端同地域,网络延迟处于较低水平; - 计时单位:秒(units are seconds);
- 对照组:blobfuse(Azure 官方 FUSE 客户端),文档特别注明blobfuse 的缓存目录会被清空,用于模拟冷读场景,确保双方读取路径尽量对等。
也就是说,该基准测试比较的是“同一地域、同规格机器”下 goofys 与 blobfuse 作为用户态 FUSE 文件系统访问同一 Azure 容器的端到端耗时,而非底层 API 的纯带宽测试。
一键复现:运行 Azure 基准测试
文档给出了完整的复现命令。基准测试以 Docker 镜像形式分发(镜像构建过程见 bench/Dockerfile.azure,入口脚本为 bench/run_bench.sh):
$ export AZURE_STORAGE_ACCOUNT=myaccount $ export AZURE_STORAGE_KEY=STORAGE-ACCESS-KEY $ sudo docker run -e BUCKET=$TESTBUCKET -e AZURE_STORAGE_ACCOUNT=$AZURE_STORAGE_ACCOUNT -e AZURE_STORAGE_KEY=$AZURE_STORAGE_KEY --rm --privileged --net=host -v /mnt/cache:/tmp/cache kahing/goofys-bench:azure-latest # result will be written to $TESTBUCKET各参数含义与作用如下:
| 参数 | 含义 |
|---|---|
AZURE_STORAGE_ACCOUNT | Azure 存储账户名,goofys 通过它定位账户并解析出 Blob 服务端点(见 conf_azure.go 的AzureBlobConfig逻辑) |
AZURE_STORAGE_KEY | 存储账户的访问密钥(Storage Access Key),用于 SharedKey 签名 |
BUCKET | 被测容器(container)名,运行结束后结果文件会被回写到该容器 |
--privileged | 授予容器挂载 FUSE 所需的权限(如访问/dev/fuse、执行fusermount) |
--net=host | 复用宿主机网络,避免容器 NAT 带来的网络性能偏差 |
-v /mnt/cache:/tmp/cache | 将宿主机/mnt/cache映射为容器内/tmp/cache,该目录被用作 blobfuse 的临时缓存路径与 goofys/catfs 的数据缓存目录 |
--rm | 测试结束后自动清理容器 |
容器内 run_bench.sh 会依次完成:启动挂载进程 → 运行各轮测试 → 收集bench.goofys、bench.blobfuse、bench.data、bench.png等结果文件 → 通过 goofys 自身把结果写回$TESTBUCKET容器。
从 run_bench.sh 的源码可以看出,脚本支持以下可调环境变量,便于控制测试范围与深度:
| 变量 | 默认值 | 作用 |
|---|---|---|
BUCKET | goofys-bench | 被测容器名 |
FAST | false | 设为true时每个测试只迭代 1 次,且 1GB 大文件降为 100MB,用于快速验证 |
CACHE | false | 设为true时启用磁盘缓存(goofys 使用--cache /tmp/cache),可额外生成缓存模式下的图表 |
ENDPOINT | http://s3-us-west-2.amazonaws.com/ | S3 模式下的端点;Azure 模式下会被置空并由 goofys 自动探测 |
基准测试指标设计
所有指标都由 bench/bench.sh 定义。该脚本接受<mount cmd> <dir> [test name]三个参数,test name决定运行哪一组操作。核心指标及其底层实现如下:
| 指标 | 实现方式(对应 bench.sh 函数) | 测量内容 |
|---|---|---|
create_files | echo $i > file$i循环 100 次 | 顺序创建 100 个文件的端到端耗时 |
create_files_parallel | 100 个(echo ... &)后台并行创建 | 并行创建 100 个文件的耗时 |
rm_files/rm_files_parallel | rm file$i顺序 / 并行删除 | 删除 100 个文件的耗时 |
write_md5 | openssl enc -aes-256-ctr生成随机流,经tee同时写largefile(默认 1GB)并计算 md5 | 写入 1GB 数据的耗时,同时保留 md5 供后续校验 |
read_md5 | md5sum largefile并比对写入时记录的MD5 | 读取 1GB 数据并校验完整性的耗时 |
read_first_byte | dd if=largefile of=/dev/null bs=1 count=1 iflag=nocache | 冷启动场景下读到第一个字节的延迟(反映对象存储流式读的响应速度) |
ls_files | ls -1 --color=always \| wc -l,先并行创建 2000 个文件 | 含 1000+ 文件的目录ls耗时 |
find_files | find \| wc -l,先并行创建 9×9×9 的目录树(共 820 个文件/目录) | 递归遍历目录树的耗时 |
脚本还保证了测量环境的“公平性”:
- 每轮测试前执行
drop_cache,即echo 3 > /proc/sys/vm/drop_caches,清空操作系统页面缓存(bench.sh 第 124-128 行); CACHE=false时每次测试前清空/tmp/cache;- 对 blobfuse 采取更严格的隔离:每轮测试前卸载并重新挂载 blobfuse,彻底清空其缓存(第 141-152 行),这正是文档中“cache directory is cleared to simulate cold read”的来源;
- 默认
iter=10,即每个指标重复 10 轮取统计量;TRAVIS或FAST模式下降为 1 轮。
read_md5会校验读取数据的 md5 与写入时一致,不一致则报错退出,因此读测试结果同时验证了数据完整性,并非单纯计时。
结果数据:goofys vs blobfuse
文档引用 bench/azure/bench.data 中的汇总数据(由 10 轮原始记录经异常值过滤后统计得到)。以下是该文件完整数据的整理(单位:秒):
| 操作 | goofys 均值(min/max) | blobfuse 均值(min/max) |
|---|---|---|
| Create 100 files | 2.67(2.52 / 2.80) | 4.40(4.31 / 4.52) |
| Create 100 files (parallel) | 0.54(0.51 / 0.63) | 2.12(2.05 / 2.17) |
| Unlink 100 files | 1.33(1.24 / 1.42) | 2.47(2.38 / 2.57) |
| Unlink 100 files (parallel) | 1.29(1.15 / 1.46) | 2.36(2.19 / 2.56) |
| ls with 1000 files | 0.53(0.50 / 0.57) | 0.39(0.26 / 1.25) |
findwith 1000 dirs/files | 2.06(1.81 / 2.41) | 3.31(2.87 / 4.17) |
| Write 1GB | 3.84(3.72 / 3.95) | 6.58(6.36 / 6.72) |
| Read 1GB | 4.86(4.71 / 4.97) | 5.46(5.15 / 5.97) |
| Time to 1st byte | 0.13(0.10 / 0.16) | 3.15(2.92 / 3.94) |
(表中数据均来自 bench/azure/bench.data,10 轮样本的均值与 min/max 范围;原始逐轮记录见 bench/azure/bench.goofys 与 bench/azure/bench.blobfuse。)
从本次测试结果可以客观观察到几组关键差异:
- 元数据操作(create/unlink):goofys 在顺序与并行场景下均快于 blobfuse,其中并行创建 100 个文件差距最明显(0.54s vs 2.12s)。这与 goofys “尽可能少的 API 调用、重读时补齐属性”的设计取向一致。
- 大文件读写(Write/Read 1GB):goofys 写入 1GB 约 3.84s,blobfuse 约 6.58s;读取约 4.86s vs 5.46s,差距小于写入。
- 首字节延迟(Time to 1st byte):goofys 平均 0.13s,blobfuse 平均 3.15s,是本次测试中差距最大的单项。这反映了冷读场景下从发起读取到数据到达用户态缓冲的响应速度。
ls单项例外:1000 文件的目录列举中 blobfuse 均值(0.39s)略快于 goofys(0.53s),但其 min/max 波动极大(0.26s~1.25s),而 goofys 稳定在 0.50s~0.57s 区间。单项均值不构成整体结论,且该数据仅代表本次单机单地域测试,不应外推为普适性能结论。
基准测试结果图
下图即为 Azure 基准测试文档 中引用的官方结果图(由 bench_graph.gnuplot 渲染,三个分段面板分别展示不同耗时量级的操作):
该图由 bench_format.py 输出的汇总数据驱动:脚本对 10 轮原始记录计算均值与标准差,剔除偏离均值超过 2 倍标准差的异常点后重新求均值与 min/max,再交由 gnuplot 以带误差条的直方图形式呈现(bench_graph.gnuplot 第 12-13 行)。
数据流水线:从原始日志到成图
仓库完整保留了“原始记录 → 汇总 → 成图 → 回写”的流水线,这也是该基准测试可复现、可信的原因:
- 原始记录:run_bench.sh 对
$PROG(此处为 blobfuse)和 goofys 分别调用bench.sh,把每次计时追加写入bench.goofys/bench.blobfuse,每行形如create_files 2.778(操作名 + 秒); - 汇总:
paste合并两组日志后交给 bench_format.py,输出 bench.data 的#operation,time表格(每行依次为操作名、goofys 均值/min/max、blobfuse 均值/min/max),同时完成操作名到中文可读标签的映射(如write_md5→Write 1GB); - 成图:
gnuplot -c bench_graph.gnuplot生成横向柱状图,convert -rotate 90旋转为最终可读方向(run_bench.sh 第 165-172 行); - 回写:测试结束前,脚本通过临时挂载 goofys 把所有结果文件
cp进被测容器bench-mnt/,这就是文档中“result will be written to $TESTBUCKET”的实现(第 77-93 行)。
源码视角:goofys 的 Azure Blob 后端如何工作
基准测试只是表象,goofys 能在 Azure 上运行,依赖其原生 Azure Blob 后端实现:
- 后端选择:goofys.go 的
NewBackend根据FlagStorage.Backend类型分派,其中*AZBlobConfig对应NewAZBlob(实现在 backend_azblob.go,基于 Azure 官方azure-storage-blob-goSDK)。 - bucket 规格解析:ParseBucketSpec 支持
wasb://container、wasb://container:prefix以及wasb://container@storage-end-point三种形态——文档中“prefix separator is:”的约定正源于此:非完整 URI 时以冒号分隔前缀,完整 URI 时则以路径形式表达前缀。 - 凭证与端点解析:conf_azure.go 的
AzureBlobConfig按优先级依次读取:URL 中内嵌的存储端点(@之后部分)→AZURE_STORAGE_ACCOUNT/AZURE_STORAGE_KEY环境变量 →~/.azure/config的[storage]段;三者均缺失时,还会回退到 Azure CLI 登录令牌(az login)并尝试通过管理 API 自动发现账户端点与密钥(第 286-415 行)。这正是 README 中AZURE_STORAGE_ACCOUNT/AZURE_STORAGE_KEY两个环境变量能直接驱动基准测试的原因。 - 兼容性细节:backend_azblob.go 中有一个值得注意的实现细节:Go 的
net/http会把请求头规范化为驼峰形式,而 Azure Blob 服务对头名大小写敏感,因此代码包装了 pipeline,把x-ms-meta-前缀的头统一转为小写再发送,避免元数据(如目录标记hdi_isfolder)丢失。
需要说明的是:本文基准数据仅覆盖 goofys 与 blobfuse 两个对象,测试环境为文档指定的单地域同机房场景。若需在 S3、GCS 等其他后端下对比,仓库还提供了对应的 bench/Dockerfile、bench/Dockerfile.gcs 与 run_bench.sh 的通用入口,可参照同一套指标自行复跑。
复现注意事项与限制
最后,根据仓库中的脚本逻辑,列出复现或扩展测试时需要留意的边界:
- 必须是具备 FUSE 权限的 Linux 环境:挂载、
fusermount -u、/proc/sys/vm/drop_caches都需要 root / privileged 权限,这也是 Docker 命令带--privileged的原因; - 清缓存是结果可信的前提:比较冷读场景时,务必保证
CACHE=false且缓存目录被清空(blobfuse 依赖重新挂载实现),否则读指标会被本地缓存“污染”; - Azure 凭证优先级:
AZURE_STORAGE_ACCOUNT/AZURE_STORAGE_KEY可覆盖~/.azure/config配置;goofys 尚不支持connection_string或sas_token(见 README-azure.md); - 结果是相对参考而非绝对基准:数值随实例规格、地域、容器内数据规模、网络状况变化,文中所有数据仅代表本次
Standard DS4 v2(West US)测试的观测值,引用时需注明前提。
如需深入阅读,可继续查看:Azure 配置使用文档、Azure 后端实现、凭证与端点解析 以及 基准测试主脚本。
- 存储
【免费下载链接】goofys
a high-performance, POSIX-ish Amazon S3 file system written in Go
相关推荐
Apache APISIX 基准测试(Benchmark)全指南:测试环境、性能结果与本地复现方法
Apache APISIX 基准测试(Benchmark)全指南:测试环境、性能结果与本地复现方法 本指南以 Apache APISIX 官方基准测试文档为主体
API网关后端云原生微服务PraisonAI Agents 实例化性能基准测试:方法与结果深度解读
PraisonAI Agents 实例化性能基准测试:方法与结果深度解读 导读 本篇围绕 PraisonAI 仓库中 SIMPLE_BENCHMARK_RESU
人工智能AI AgentAgent 框架多智能体工作流自动化RAGMCP 服务ShapeMask 在 Cloud TPU 上的扩展性基准测试:测量方法、结果与完整复现指南
ShapeMask 在 Cloud TPU 上的扩展性基准测试:测量方法、结果与完整复现指南 本文基于 benchmarks/ShapeMask_Perform
深度学习后端开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考