全部产品
Search
文档中心

Object Storage Service:panduan pengujian performa ossfs 2.0

更新时间:Nov 26, 2025

Pengujian ini membandingkan performa berbagai versi ossfs dan tool open-source goofys dalam berbagai skenario, termasuk kecepatan baca-tulis file dan operasi konkuren. Hasilnya memberikan referensi performa untuk membantu Anda memilih tool yang tepat bagi bisnis Anda.

Lingkungan pengujian

  • Lingkungan Perangkat Keras

    • Jenis instance: ecs.g9i.48xlarge

    • vCPU: 192 vCPU

    • Memori: 768 GiB

    • Bandwidth jaringan: 64 Gbps

  • Lingkungan Perangkat Lunak

    • Sistem operasi: Alibaba Cloud Linux 3.2104 LTS 64-bit

    • Versi kernel: 5.10.134-18.al8.x86_64

    • Versi tool: ossfs 2.0.4, ossfs 1.91.8, dan goofys 0.24.0

Konfigurasi Mount

Contoh berikut menunjukkan opsi mount yang digunakan dalam pengujian performa.

Catatan

Pengujian ini menggunakan Nama domain HTTPS. Di lingkungan tepercaya, Anda dapat melakukan mount dengan Nama domain HTTP. Metode ini mengonsumsi lebih sedikit sumber daya CPU untuk throughput yang sama.

ossfs 2.0.4

  • File Konfigurasi Pemasangan (ossfs2.conf)

    Saat bucket dimount, ukuran bagian unggah diatur menjadi 33.554.432 byte.

    # Titik akhir wilayah bucket
    --oss_endpoint=https://oss-cn-hangzhou-internal.aliyuncs.com
    
    # Nama bucket
    --oss_bucket=bucket-test
    
    # ID AccessKey dan Rahasia AccessKey
    --oss_access_key_id=yourAccessKeyID
    --oss_access_key_secret=yourAccessKeySecret
    
    # Ukuran buffer unggah, dalam byte
    --upload_buffer_size=33554432
  • Perintah mount

    Perintah berikut menggunakan file konfigurasi ossfs2.conf untuk memount bucket bucket-test ke direktori lokal /mnt/ossfs2/.

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

ossfs 1.91.8

Perintah berikut memount bucket bucket-test ke direktori lokal /mnt/ossfs dan mengaktifkan mode baca langsung serta optimasi cache.

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

goofys 0.24.0

Perintah berikut memount bucket bucket-test ke direktori lokal /mnt/goofys.

goofys --endpoint https://oss-cn-hangzhou-internal.aliyuncs.com --subdomain bucket-test --stat-cache-ttl 60s --type-cache-ttl 60s /mnt/goofys

Skenario pengujian

Setelah bucket dimount menggunakan ossfs 2.0.4, ossfs 1.91.8, dan goofys 0.24.0, tool pengujian FIO digunakan untuk mengevaluasi kemampuan dasar baca dan tulis masing-masing tool. Skema pengujian dan hasilnya dijelaskan pada bagian berikut.

Tulisan langsung sekuensial single-threaded pada file 100 GB

Catatan

Performa tulis ossfs 1.0 dibatasi oleh performa disk.

  • Perintah Pengujian

    Perintah berikut menggunakan tool FIO untuk menjalankan pengujian tulis langsung single-threaded bernama file-100G. Total data 100 GB ditulis dengan ukuran blok 1 MB ke direktori /mnt/oss/fio_direct_write dan menghasilkan output hasil pengujian.

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

    Tool

    Bandwidth

    Pemanfaatan core CPU (100% untuk satu core yang sepenuhnya dimuat)

    Memori puncak

    ossfs 2.0

    2,2 GB/s

    207%

    2.167 MB

    ossfs 1.0

    118 MB/s

    5%

    15 MB

    goofys

    450 MB/s

    250%

    7,5 GB

Baca sekuensial single-threaded pada file 100 GB

  • Perintah Pengujian

    Perintah berikut pertama-tama mengosongkan cache halaman sistem. Kemudian, menggunakan tool FIO untuk menjalankan pengujian baca sekuensial single-threaded pada file 100 GB di direktori /mnt/oss/fio_direct_write. Pengujian menggunakan ukuran blok 1 MB dan menghasilkan output hasil pengujian.

    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
  • Hasil Pengujian

    Alat pengujian

    Bandwidth

    Pemanfaatan core CPU (100% untuk satu core yang sepenuhnya dimuat)

    Memori puncak

    ossfs 2.0

    4,3 GB/detik

    610%

    1629 MB

    ossfs 1.0

    1,0 GB/detik

    530%

    260 MB

    goofys

    1,3 GB/s

    270%

    976 MB

Pembacaan sekuensial multi-threaded dari file 100 GB

  • Hasilkan File Pengujian

    Perintah berikut membuat empat file berukuran 100 GB di direktori mount /mnt/oss/fio untuk pengujian konkurensi multi-threaded.

    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
  • Perintah Pengujian

    Perintah berikut pertama-tama mengosongkan cache halaman sistem. Kemudian, menggunakan tool FIO untuk menjalankan pengujian baca selama 30 detik dengan empat thread konkuren pada empat file 100 GB di direktori /mnt/oss/fio. Pengujian menggunakan ukuran blok 1 MB dan menghasilkan output hasil pengujian.

    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
  • Hasil Pengujian

    Tool

    Bandwidth

    Pemanfaatan core CPU (100% untuk satu core yang sepenuhnya dimuat)

    Memori puncak

    ossfs 2.0

    7,4 GB/detik

    890%

    6,2 GB

    ossfs 1.0

    1,8 GB/detik

    739%

    735 MB

    goofys

    2,8 GB/s

    7800%

    2,7 GB

Pembacaan konkuren 100.000 file berukuran 128 KB dengan 128 thread

Catatan

Secara default, OSS memiliki batas 10.000 permintaan per detik (QPS). Untuk mencapai metrik performa yang ditunjukkan dalam hasil pengujian, pastikan layanan lain tidak mengonsumsi QPS akun pengujian.

  • Langkah-langkah

    1. Buat program Go bernama rw-bench.go.

      Program ini memiliki dua fungsi utama: membuat banyak file berukuran sama secara konkuren di direktori target, dan membaca semua file di direktori target secara konkuren. Selama operasi baca, program mendistribusikan file ke jumlah thread tertentu dan mencatat bandwidth akhir.

      Kode Sampel

      package main
      
      import (
      	"flag"
      	"fmt"
      	"io"
      	"log"
      	"os"
      	"path/filepath"
      	"sync"
      	"time"
      )
      
      var dir = flag.String("dir", "", "direktori kerja")
      var threads = flag.Int("threads", 8, "jumlah thread konkuren")
      var isWrite = flag.Bool("write", false, "uji penulisan file")
      var fileSize = flag.Int64("file-size-KB", 128, "ukuran file dalam KByte")
      var fileCount = flag.Int("file-count", 0, "jumlah file")
      
      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("Gagal membuat/membuka %v dengan %v\n", fInfo.Name, err)
      				continue
      			}
      		} else {
      			fd, err = os.OpenFile(fInfo.Name, os.O_RDONLY, 0)
      			if err != nil {
      				fmt.Printf("Gagal membuka %v dengan %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("Gagal menulis file %v pada %v, dengan %v\n", fInfo.Name, offset, err)
      					break
      				}
      			} else {
      				n, err = fd.ReadAt(buffer, offset)
      				if err != nil && err != io.EOF {
      					fmt.Printf("Gagal membaca file %v pada %v, dengan %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("mulai uji tulis dengan %v file\n", len(files))
      	} else {
      		fmt.Printf("mulai uji baca dengan %v file\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 waktu: %v\n", duration)
      	if isWrite {
      		fmt.Printf("Throughput tulis: %.2f MByte/s\n", throughput/1000/1000)
      	} else {
      		fmt.Printf("Throughput baca: %.2f MByte/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("Gagal mengakses %v dengan %v\n", workdir, err)
      		os.Exit(1)
      	}
      
      	doBench(workdir, *isWrite)
      }
    2. Kompilasi file program rw-bench.go.

      go build rw-bench.go
    3. Gunakan perintah berikut untuk membuat 100.000 file, masing-masing berukuran 128 KB, di direktori lokal tempat bucket OSS dimount.

      mkdir -p <path_to_mounted_test_directory> && ./rw-bench --dir <path_to_mounted_test_directory> --file-size-KB 128 --file-count 100000 --write
    4. Kosongkan cache halaman sistem dan jalankan program. Pengujian dijalankan lima kali berturut-turut. Setelah latensi sisi server stabil, data pengujian kondisi mantap dicatat.

      echo 1 > /proc/sys/vm/drop_caches
      ./rw-bench --dir <path_to_mounted_test_directory> --threads 128
  • Hasil Pengujian

    Tool

    Bandwidth

    Pemanfaatan core CPU (100% untuk satu core yang sepenuhnya dimuat)

    Memori puncak

    ossfs 2.0

    1 GB/s

    247%

    176 MB

    ossfs 1.0

    45 MB/detik

    25%

    412 MB

    goofys

    1 GB/s

    750%

    1,3 GB