赛尔校园公共服务平台 Logo
平台使用
阿里云
百度云
移动云
智算服务
教育生态
登录 →
赛尔校园公共服务平台 Logo
平台使用 阿里云 百度云 移动云 智算服务 教育生态
登录
  1. 首页
  2. 阿里云
  3. 对象存储
  4. 开发参考
  5. 常用工具
  6. ossfs 2.0(预览版)
  7. 性能测试

性能测试

  • ossfs 2.0(预览版)
  • 发布于 2025-04-21
  • 0 次阅读
文档编辑
文档编辑

本次测试旨在深入评估ossfs 2.0在不同场景下的性能,包括文件的读写速度、并发场景下的表现等,以便提供准确的性能参考,帮助您更好地选择和使用ossfs 2.0进行相关业务操作。

测试环境

  • 硬件环境

    • 实例规格:ecs.g7.32xlarge (128vCPU 512GiB)。

    • vCPU:128 vCPU。

    • 内存:512 GiB。

  • 软件环境

    • 操作系统:Alibaba Cloud Linux 3.2104 LTS 64位。

    • 内核版本:5.10.134-18.al8.x86_64。

    • ossfs版本:ossfs 2.0.0beta、ossfs 1.91.4。

挂载配置

以下为ossfs性能测试中所使用的挂载选项示例。

ossfs 2.0.0beta

  • 挂载配置文件(ossfs2.conf)

    在挂载Bucket时,指定上传文件分片大小为33554432 Bytes。

    # Bucket所处Endpoint(地域节点)
    --oss_endpoint=https://oss-cn-hangzhou-internal.aliyuncs.com
    
    # Bucket名称
    --oss_bucket=bucket-test
    
    # 访问密钥AccessKey ID和AccessKey Secret
    --oss_access_key_id=yourAccessKeyID
    --oss_access_key_secret=yourAccessKeySecret
    
    # 上传文件分片大小,单位Bytes
    --upload_buffer_size=33554432
  • 挂载命令

    指定挂载配置文件ossfs2.conf,将bucket-test挂载到本地/mnt/ossfs2/目录。

    ossfs2 mount /mnt/ossfs2/ -c /etc/ossfs2.conf 

ossfs 1.91.4

将bucket-test挂载至本地/mnt/ossfs目录,同时开启直读模式与缓存优化功能。

ossfs bucket-test /mnt/ossfs -ourl=https://oss-cn-hangzhou-internal.aliyuncs.com -odirect_read -oreaddir_optimize

测试场景

使用ossfs 2.0.0beta和ossfs 1.91.4挂载Bucket存储空间后,运用FIO测试工具,分别针对ossfs 2.0与ossfs 1.0的基本读写能力展开测试。具体测试场景及结果如下。

单线程顺序直写100 GB文件

说明

ossfs 1.0的写入性能受磁盘性能制约。

  • 测试命令

    使用FIO工具,执行名为file-100G的单次单线程直接写测试任务,块大小为1 MB,写入总量100 GB的数据到/mnt/oss/fio_direct_write目录并输出测试结果。

    fio --name=file-100G --ioengine=libaio --rw=write --bs=1M --size=100G --numjobs=1 --direct=1 --directory=/mnt/oss/fio_direct_write --group_reporting
  • 测试结果

    ossfs版本

    带宽

    CPU核心占用率(单个核心满载为100%)

    峰值内存

    ossfs 2.0

    2.2 GB/s

    207%

    2167 MB

    ossfs 1.0

    118 MB/s

    5%

    15 MB

单线程顺序读取100 GB文件

  • 测试命令

    清除系统页面缓存,再用FIO工具对/mnt/oss/fio_direct_write目录下的100 GB文件进行单线程、块大小1 MB的顺序读测试并输出测试结果。

    echo 1 > /proc/sys/vm/drop_caches
    fio --name=file-100G --ioengine=libaio --direct=1 --rw=read --bs=1M --directory=/mnt/oss/fio_direct_write --group_reporting --numjobs=1
  • 测试结果

    ossfs版本

    带宽

    CPU核心占用率(单个核心满载为100%)

    峰值内存

    ossfs 2.0

    3.0 GB/s

    378%

    1617 MB

    ossfs 1.0

    355 MB/s

    50%

    400 MB

多线程顺序读取100 GB文件

  • 生成测试文件

    在挂载目录/mnt/oss/fio下创建4个100 GB的文件用于多线程并发测试。

    fio --name=file-100g --ioengine=libaio --direct=1 --iodepth=1 --numjobs=4 --nrfiles=1 --rw=write --bs=1M  --size=100G --group_reporting --thread --directory=/mnt/oss/fio
  • 测试命令

    清除系统页面缓存,再用FIO工具通过4个并发线程对/mnt/oss/fio目录下的4个100 GB文件进行1 MB块大小的30秒读取测试,并输出测试结果。

    echo 1 > /proc/sys/vm/drop_caches
    fio --name=file-100g --ioengine=libaio --direct=1 --iodepth=1 --numjobs=4 --nrfiles=1 --rw=read --bs=1M  --size=100G --group_reporting --thread --directory=/mnt/oss/fio --time_based --runtime=30
  • 测试结果

    ossfs版本

    带宽

    CPU核心占用率(单个核心满载为100%)

    峰值内存

    ossfs 2.0

    7.1 GB/s

    1187%

    6.2 GB

    ossfs 1.0

    1.4 GB/s

    210%

    1.6 GB

128线程并发读10万128 KB文件

说明

OSS默认提供10000的QPS限制。若要达到测试结果中的性能指标,需要确保测试账号的QPS不会被其他业务占用。

  • 测试步骤

    1. 创建名为rw-bench.go的Go语言程序。

      此程序具备两项核心功能。其一,它能够并发地在目标文件目录下创建若干个大小相同的文件;其二,它可以并发读取目标文件目录下的所有文件,将这些文件分配给n个线程进行读取操作,并且记录最终的带宽数据。

      代码示例

      package main
      
      import (
      	"flag"
      	"fmt"
      	"io"
      	"log"
      	"os"
      	"path/filepath"
      	"sync"
      	"time"
      )
      
      var dir = flag.String("dir", "", "work dir")
      var threads = flag.Int("threads", 128, "concurrency threads count")
      var isWrite = flag.Bool("write", false, "test write files")
      var fileSize = flag.Int64("file-size-KB", 128, "file size in KBytes")
      var fileCount = flag.Int("file-count", 0, "file count")
      
      type fileInfo struct {
      	Name string
      	Size int64
      }
      
      func getFileList(dir string, isWrite bool) []fileInfo {
      	var files []fileInfo
      
      	if isWrite {
      		for i := 0; i < *fileCount; i++ {
      			files = append(files, fileInfo{
      				Name: fmt.Sprintf("%v/%v.dat", dir, i),
      				Size: *fileSize * 1024,
      			})
      		}
      	} else {
      		err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
      			if err != nil {
      				return err
      			}
      			if !info.IsDir() {
      				files = append(files, fileInfo{
      					Name: path,
      					Size: info.Size(),
      				})
      			}
      			return nil
      		})
      
      		if err != nil {
      			log.Fatalf("Error walking the path %v: %v\n", dir, err)
      		}
      	}
      
      	return files
      }
      
      func worker(taskChan <-chan fileInfo, wg *sync.WaitGroup, bytesChan chan<- int64, isWrite bool) {
      	defer wg.Done()
      	buffer := make([]byte, 1024*1024)
      
      	for fInfo := range taskChan {
      		var fd *os.File
      		var err error
      		if isWrite {
      			fd, err = os.OpenFile(fInfo.Name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
      			if err != nil {
      				fmt.Printf("Failed to create/open %v with %v\n", fInfo.Name, err)
      				continue
      			}
      		} else {
      			fd, err = os.OpenFile(fInfo.Name, os.O_RDONLY, 0)
      			if err != nil {
      				fmt.Printf("Failed to open %v with %v\n", fInfo.Name, err)
      				continue
      			}
      		}
      
      		offset := int64(0)
      		var totalBytes int64
      		for offset < fInfo.Size {
      			var n int
      
      			if offset+int64(len(buffer)) > fInfo.Size {
      				buffer = buffer[:fInfo.Size-offset]
      			}
      
      			if isWrite {
      				n, err = fd.WriteAt(buffer, offset)
      				if err != nil {
      					fmt.Printf("Failed to write file %v at %v, with %v\n", fInfo.Name, offset, err)
      					break
      				}
      			} else {
      				n, err = fd.ReadAt(buffer, offset)
      				if err != nil && err != io.EOF {
      					fmt.Printf("Failed to read file %v at %v, with %v\n", fInfo.Name, offset, err)
      					break
      				}
      			}
      
      			totalBytes += int64(n)
      			offset += int64(n)
      		}
      
      		fd.Close()
      		bytesChan <- totalBytes
      	}
      }
      
      func doBench(dir string, isWrite bool) {
      	files := getFileList(dir, isWrite)
      	var wg sync.WaitGroup
      
      	if isWrite {
      		fmt.Printf("start write bench with %v files\n", len(files))
      	} else {
      		fmt.Printf("start read bench with %v files\n", len(files))
      	}
      
      	taskChan := make(chan fileInfo, 1024)
      
      	go func(taskChan chan<- fileInfo) {
      		for _, fInfo := range files {
      			taskChan <- fInfo
      		}
      		close(taskChan)
      	}(taskChan)
      
      	bytesChan := make(chan int64, 1024)
      	for i := 0; i < *threads; i++ {
      		wg.Add(1)
      		go worker(taskChan, &wg, bytesChan, isWrite)
      	}
      
      	st := time.Now()
      	go func() {
      		wg.Wait()
      		close(bytesChan)
      	}()
      
      	var totalBytes int64
      	for bytes := range bytesChan {
      		totalBytes += bytes
      	}
      
      	ed := time.Now()
      	duration := ed.Sub(st)
      	throughput := float64(totalBytes) / (float64(duration.Nanoseconds()) / 1e9)
      
      	fmt.Printf("Total time: %v\n", duration)
      	if isWrite {
      		fmt.Printf("Write throughput: %.2f MBytes/s\n", throughput/1000/1000)
      	} else {
      		fmt.Printf("Read throughput: %.2f MBytes/s\n", throughput/1000/1000)
      	}
      }
      
      func main() {
      	flag.Parse()
      
      	workdir := *dir
      	if workdir == "" {
      		flag.Usage()
      		os.Exit(1)
      	}
      
      	if _, err := os.Stat(workdir); err != nil {
      		fmt.Printf("Failed to access %v with %v\n", workdir, err)
      		os.Exit(1)
      	}
      
      	doBench(workdir, *isWrite)
      }
      
    2. 编译rw-bench.go程序文件。

      go build rw-bench.go
    3. 在已挂载到本地的OSSBucket目录中,创建100000个128 KB大小的文件。

      mkdir -p <已挂载测试文件夹路径> && ./rw-bench --dir <已挂载测试文件夹路径> --file-size-KB 128 --file-count 100000 --write
    4. 清除系统页面缓存并执行该程序,连续开展5次测试。在服务端时延趋于稳定后取稳态测试数据。

      echo 1 > /proc/sys/vm/drop_caches
      ./rw-bench --dir <已挂载测试文件夹路径> --threads 128
  • 测试结果

    ossfs版本

    带宽

    CPU核心占用率(单个核心满载为100%)

    峰值内存

    ossfs 2.0

    1 GB/s

    247%

    212 MB

    ossfs 1.0

    3.5 MB/s

    3%

    200 MB

相关文章

安装ossfs 2.0 2025-04-21 17:18

本文为您介绍如何在Linux系统中安装ossfs 2.0。 重要 目前,ossfs 2.0仅支持在Aliba

配置ossfs 2.0 2025-04-21 17:18

在实际使用过程中,为满足不同场景下对存储空间(OSS Bucket)的挂载需求,需对ossfs 2.0配置文件进行针对性配置,然后在挂载存储空间(OSS Bucket)时,引用该配置文件即可完成挂载。本文将为您介绍,如何通过挂载选项,生成适用不同场景的ossfs 2.0配置文件。 创建配置文件

挂载存储空间 2025-04-21 17:18

本文为您介绍,如何在Linux系统中使用ossfs 2.0将对象存储(OSS)中的存储空间(Bucket)挂载到本地文件系统。 前提条件 已安装ossfs 2.0并配置ossfs 2.0。

挂载选项说明 2025-04-21 17:18

在编写ossfs 2.0配置文件时,您可以根据不同的挂载需求,灵活配置各项参数,生成符合特定场景的配置文件。通过该配置文件,您可以轻松实现对OSS Bucket的多样化文件系统挂载,满足不同业务场景的需求。 基础配置项 <

性能测试 2025-04-21 17:18

本次测试旨在深入评估ossfs 2.0在不同场景下的性能,包括文件的读写速度、并发场景下的表现等,以便提供准确的性能参考,帮助您更好地选择和使用ossfs 2.0进行相关业务操作。 测试环境 硬件环境

常见问题 2025-04-21 17:18

本文为您介绍在使用ossfs 2.0时遇到的常见问题及其解决方案。 通用说明 ossfs 2.0报错信息中均含有HTTP请求的报错信息。排查问题时,可以根据日志中对应的HTTP响应状态码4**、<

目录
Copyright © 2025 your company All Rights Reserved. Powered by 赛尔网络.
京ICP备14022346号-15
gongan beian 京公网安备11010802041014号